用Typescript类型来实现快排

网站建设4年前发布
26 0 0

写在前面 本文执行环境typescript,版本4.7.4,能否将元组 [3, 1, 2, 4] 通过泛型转换成 [1, 2, 3, 4],如何实现快排?,• 遍历元组,• 元组每个值的大小比较,• 每次比较中挑选出符合条件的值,也就是实现 Filter,在typescript类型中没有比较符,那如何判断 5 和 6 谁更大?,typescript类型不知道,所以需要找到在typescript中已经存在的递增数列,通过这个数列来实现,类似有 张三 和 李四 两个人,要比较他们谁的位置靠前,需要有一个他们排队的数列,然后依次查看,先看到 张三,那么 张三 的位置明显靠前,typescript中有这样的递增数列吗?,有的:元组下标(取元祖长度,元祖push的时候长度是递增的数列),只需要递归元组,就可以实现依次点名,• 无限递归,直到匹配到 A 或者 B,• 先匹配到 A 返回true(表示A小于或等于B),否则返回false,逻辑同理,• 无限递归,直到匹配到 A 或者 B,• 先匹配到 A 返回false,否则返回true(表示A大于或等于B),当然也可以依赖 SmallerThan 泛型来实现,• 与SmallerThan的布尔值取反,• 根据元组长度递归,直到递归次数与元祖长度相等,• 当满足条件(比如:大于等于某个值),将值存储到新元组中,否则不操作,• 依赖上面实现的大小值比较 分别实现 对应的Filter,基于已有的 LargerThan 泛型实现 FilterLargerThan,同理,基于已有的 SmallerThan 泛型实现 FilterSmallerThan,Filter写的很重复了,根据DRY原则(don't repeat yourself),需要将泛型作为参数传进去,来避免冗余重复的代码,如何把泛型作为参数传入,然后在参数中限定?,嗯...好问题,貌似不太行,那变个思路:,实现一个泛型对象,每个键值对实现对应的处理,最后只需要传入这个对象的key来获取泛,型,在参数的限定可以变成对key的限定,通过keyof 对象即可实现,• 实现一个泛型对象Demo,• 每个键值对实现对应的处理,如 a: F,• 传入这个对象的key来获取泛型,如 T extends keyof Demo,• 根据上述原则,将对应的泛型组合成泛型对象 Compare,• SmallerThan 实现之前的 SmallerThan 泛型,• LargerThan 实现之前的 LargerThan 泛型,• 将对应的泛型改成 Compare,• key需要手动传入,即为字符串 SmallerThan 和 LargerThan,• 递归元组,直到拆解为长度 0 或者 1 的元祖,• 元组长度小于等于 1 的时候返回自身,• 默认取第一项作为对比值,并用泛型 UNSHIFT 移除第一项,• 通过filter和第一项比较筛选出对应的新元祖,看起来一切正常,可以发现遗漏了负数,测试负数的时候问题出现了,因为最开始的大小值对比,是从0开始无限递归的,结束条件是命中其中一个数,然而负数是永远不会命中,这就是致命bug!,负数的特点:多了一个符号,也就是 "-",• 转换成字符串后取第一个字符判断是否为 "-",• 通过 infer 来获取第一个字符,但是这样拿到的是字符串,还要把字符串转成数字,和大小比较的逻辑一样,• 无限递归,每次递归传入新元组,• 元组长度(模板字符串) 等于 参数后结束递归,并返回元组长度,判断是负数后要拿到负数的值,• 和负数符号判断类似,获取除开符号之后的字符串,• 字符串通过泛型 ToNumber 转数字,• 非负数返回自身,负数通过泛型 GetFushu 来获取,负数的对比和正数相反,且正数一定比负数大,• 判断比较的值是负数还是非负数,• 非负数通过泛型 CompareV2 比较大小,• 负数获取绝对值后,通过泛型 CompareV2 取反比较大小,• 非负数一定大于负数,• 泛型 SmallerThan 实现非负数的比较,泛型SmallerThanV2 实现负数和非负数的比较,• 泛型 LargerThan 和泛型 LargerThanV2 同理,测试用例,重构泛型 FilterV2(更换 Compare -> CompareV2)

© 版权声明

相关文章