通过typescript类型实现元组快排怎样做
Admin 2022-09-01 群英技术资讯 1221 次浏览
本篇内容介绍了“通过typescript类型实现元组快排怎样做”的有关知识,在实际项目的操作过程或是学习过程中,不少人都会遇到这样的问题,接下来就让小编带大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!不使用typescript的计算能力,通过类型来实现快排
能否将元组 [3, 1, 2, 4] 通过泛型转换成 [1, 2, 3, 4]
如何实现快排?
在typescript类型中没有比较符,那如何判断 5 和 6 谁更大?
typescript类型不知道,所以需要找到在typescript中已经存在的递增数列,通过这个数列来实现
怎么理解呢?
类似有 张三 和 李四 两个人,要比较他们谁的位置靠前,需要有一个他们排队的数列,然后依次查看,先看到 张三,那么 张三 的位置明显靠前
typescript中有这样的递增数列吗?
有的:元组下标,只需要递归元组,就可以实现依次点名
type SmallerThan<
A extends number,
B extends number,
T extends number[] = []
> = T['length'] extends A ? true :
T['length'] extends B ? false :
SmallerThan<A, B, [...T, 0]>;
逻辑同理:
无限递归,直到匹配到 A 或者 B
type LargerThan<
A extends number,
B extends number,
T extends number[] = []
> = T['length'] extends A ? false :
T['length'] extends B ? true :
LargerThan<A, B, [...T, 0]>;
当然也可以依赖 SmallerThan 泛型来实现
type LargerThan<
A extends number,
B extends number,
T extends number[] = []
> = SmallerThan<A, B, T> extends true ? false : true;
type FilterLargerThan<
T extends number[],
A extends number,
Z extends number[] = [],
R extends number[] = []
> = T['length'] extends R['length'] ?
Z : FilterLargerThan<
T,
A,
LargerThan<T[R['length']], A> extends true ? [...Z, T[R['length']]] : Z,
[...R, 0]
>;
type FilterSmallerThan<
T extends number[],
A extends number,
Z extends number[] = [],
R extends number[] = []
> = T['length'] extends R['length'] ?
Z : FilterSmallerThan<
T,
A,
SmallerThan<T[R['length']], A> extends true ? [...Z, T[R['length']]] : Z,
[...R, 0]
>;
Filter写的很重复了,将泛型作为参数传进去
如何把泛型作为参数传入,然后在参数中限定...好问题
// 目标是实现这种 type Test<A extends number, T extends ?> = T<A>;
貌似不太行,那变个思路:
实现一个对象,每个键值对实现一个泛型,最后只需要传入这个对象的key来获取泛型,在参数的限定可以变成对key的限定,通过keyof 对象即可实现
type F<A extends number> = A;
type Demo<A extends number> = {
a: F<A>;
}
type Test<A extends number, T extends keyof Demo<number>> = Demo<A>[T];
type t1 = Test<1, 'a'>;
复用逻辑,将对应的泛型改成键值对
type Compare<A extends number, B extends number, T extends number[] = []> = {
['SmallerThan']:
T['length'] extends A ? true :
T['length'] extends B ? false :
Compare<A, B, [...T, 0]>['SmallerThan'];
['LargerThan']:
T['length'] extends A ? false :
T['length'] extends B ? true :
Compare<A, B, [...T, 0]>['LargerThan'];
}
复用逻辑,将对应的泛型改成键值对,key需要手动传入
type Filter<
T extends number[],
A extends number,
key extends keyof Compare<number, number>,
Z extends number[] = [],
R extends number[] = [],
> = T['length'] extends R['length'] ?
Z : Filter<
T,
A,
key,
Compare<T[R['length']], A>[key] extends true ? [...Z, T[R['length']]] : Z,
[...R, 0]
>;
type UNSHIFT<T extends number[]> = T extends [number, ...infer U] ? U: [];
// 快排
type QuickSort<T extends any[]> = T['length'] extends 0 | 1 ?
T : [
...QuickSort<Filter<UNSHIFT<T>, T[0], 'SmallerThan'>>,
T[0],
...QuickSort<Filter<UNSHIFT<T>, T[0], 'LargerThan'>>
];
type ARR1 = [5, 2, 4, 1, 0, 6]; type test1 = QuickSort<ARR1>; // [0, 1, 2, 4, 5, 6] type ARR2 = [3, 2, 7, 1, 0, 6, 9, 5, 8, 4]; type test2 = QuickSort<ARR2>; // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] type ARR3 = [1, 1, 0, 1, 1, 0, 0]; type test3 = QuickSort<ARR3>; // [0, 0, 0, 1, 1, 1, 1]
看起来一切正常,可以发现遗漏了负数
测试负数的时候问题出现了
因为最开始的大小值对比,是从0开始无限递归的
结束条件是命中其中一个数,然而负数是永远不会命中,这就是致命bug!
负数的特点:多了一个符号,也就是 '-',转换成字符串后拿第一个字符判断
type isFuShu<T extends number> = `${T}` extends `${infer P}${string}` ?
P extends '-' : true : false;
type i1 = isFuShu<6>; // false
type i2 = isFuShu<-6>; // true
但是这样拿到的是字符串,还要把字符串转成数字
和大小比较的逻辑一样
type ToNumber<S extends string, R extends number[] = []> =
S extends `${R['length']}` ?
R['length'] : ToNumber<S, [...R, 0]>;
判断是负数后要拿到负数的值
type GetFushu<T extends number> = `${T}` extends `${string}${infer U}` ?
ToNumber<U> : 0;
type GetAbs<T extends number> = isFuShu<T> extends true ? GetFushu<T> : T;
负数的对比和正数相反,且正数一定比负数大
type CompareV2<A extends number, B extends number, T extends number[] = []> = {
['SmallerThan']:
T['length'] extends A ? true :
T['length'] extends B ? false :
CompareV2<GetAbs<A>, GetAbs<B>, [...T, 0]>['SmallerThan'];
['SmallerThanV2']:
isFuShu<A> extends true ?
(isFuShu<B> extends true ?
CompareV2<A, B>['LargerThan'] :
true) :
(isFuShu<B> extends true ?
false :
CompareV2<A, B>['SmallerThan']);
['LargerThan']:
T['length'] extends A ? false :
T['length'] extends B ? true :
CompareV2<GetAbs<A>, GetAbs<B>, [...T, 0]>['LargerThan'];
['LargerThanV2']:
isFuShu<A> extends true ?
(isFuShu<B> extends true ?
CompareV2<A, B>['SmallerThan'] :
false) :
(isFuShu<B> extends true ?
true :
CompareV2<A, B>['LargerThan']);
}
测试用例:
type h1 = CompareV2<-8, -6>['SmallerThanV2']; // true type h2 = CompareV2<8, -6>['SmallerThanV2']; // false type h3 = CompareV2<6, 8>['SmallerThanV2']; // true type h4 = CompareV2<-8, 6>['SmallerThanV2']; // true type i1 = CompareV2<-8, -6>['LargerThanV2']; // false type i2 = CompareV2<8, -6>['LargerThanV2']; // true type i3 = CompareV2<6, 8>['LargerThanV2']; // false type i4 = CompareV2<-8, 6>['LargerThanV2']; // false
type FilterV2<
T extends number[],
A extends number,
key extends keyof CompareV2<number, number>,
Z extends number[] = [],
R extends number[] = [],
> = T['length'] extends R['length'] ?
Z : FilterV2<
T,
A,
key,
CompareV2<T[R['length']], A>[key] extends true ? [...Z, T[R['length']]] : Z,
[...R, 0]
>;
// 快排
type QuickSortV2<T extends any[]> = T['length'] extends 0 | 1 ?
T : [
...QuickSortV2<FilterV2<UNSHIFT<T>, T[0], 'SmallerThanV2'>>,
T[0],
...QuickSortV2<FilterV2<UNSHIFT<T>, T[0], 'LargerThanV2'>>
];
type ARR4 = [-5, -2, -4, -1, 0, -6]; type test4 = QuickSortV2<ARR4>; // [-6, -5, -4, -2, -1, 0] type ARR5 = [-5, -2, 4, -1, 0, -6, 2, -3, 7]; type test5 = QuickSortV2<ARR5>; // [-6, -5, -3, -2, -1, 0, 2, 4, 7] type ARR6 = [3, -2, 7, -1, 0, -6, 9, -5, 8, -4]; type test6 = QuickSortV2<ARR6>; // [-6, -5, -4, -2, -1, 0, 3, 7, 8, 9]
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
这篇文章主要为大家详细介绍了Vue实现简易记事本功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
我们在学习JavaScript时,回调函数是很重要的一个知识点,是大家需要掌握的内容。但是很多很多新手对于JavaScript中的回调,并不是很清楚,因此这篇文章就给大家介绍一下回调函数的概念以及如何区分两种回调:同步和异步。
今天我们来学习一下watch侦听器的好兄弟 watchEffect 侦听器。这个相对来说比较简单,用的不是很多,当然了,根据自己的项目情况自行决定使用,希望对大家有所帮助
在开发过程中,遇到异常错误是比较常见的,因此掌握异常处理很有必要。那么如果是未知异常我们要如何处理呢?下面给大家分享关于angular 异常处理的内容,感兴趣的朋友可以参考。
这篇文章主要介绍JS数组去重,关于去重实际应用中,最常用的方法就是使用Set,也可以使用第三方库lodash来处理,下面一起来看看文章是怎么介绍JS数组去重的
成为群英会员,开启智能安全云计算之旅
立即注册关注或联系群英网络
7x24小时售前:400-678-4567
7x24小时售后:0668-2555666
24小时QQ客服
群英微信公众号
CNNIC域名投诉举报处理平台
服务电话:010-58813000
服务邮箱:service@cnnic.cn
投诉与建议:0668-2555555
Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 ICP核准(ICP备案)粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008