04499-medium-chunk

Back

// 你的答案
type Chunk<T extends any[],U extends number,R extends any[] = [],S extends any[] = [],B extends any[] = [] > = S['length'] extends U ? Chunk<T,U,[...R,B],[],[]> : 
                                                            T extends [infer RR,...infer LL]? Chunk<LL,U,R,[...S,1],[...B,RR]>: B extends [] ? R : [...R,B]

Solution by yuadh #36694

// your answers
// 取出前N个
type PopN<T extends any[], N, Count extends any[] = []> = 
  Count['length'] extends N ? [] : T extends [infer R, ...infer Rest] ? [R, ...PopN<Rest,N,[...Count,1]>] : []

// 去除前N个后的剩余部分
type RestN<T extends any[], N, Count extends any[] = []> =
 Count['length'] extends N ? T : T extends [infer R, ...infer Rest] ? RestN<Rest, N, [...Count, 1]> : []

// 从T里取出0...N的数组
// chunk剩余部分
type Chunk<T extends any[], N extends number> = 
  T extends [] ? [] : [PopN<T, N>, ...Chunk<RestN<T, N>, N>]

Solution by duanlvxin #36570

type Chunk<
  T extends any[],  // T는 배열 (튜플)
  N extends number, // N은 숫자 (청크 크기)
  R extends any[] = [] // R은 임시적으로 담을 배열
> = T extends [infer First, ...infer Rest] // 첫 번째 요소를 분리
  ? R['length'] extends N // 임시 배열 R의 길이가 N이면, 한 덩어리 완성
    ? [R, ...Chunk<T, N>] // 현재 청크를 결과에 추가하고, 다시 Chunk 호출
    : Chunk<Rest, N, [...R, First]> // 현재 요소를 R에 추가하고 계속 진행
  : R extends [] // 남은 R이 비어 있으면
    ? [] // 더 이상 나눌 것이 없음
    : [R]; // 마지막 남은 청크를 추가

Solution by adultlee #35842

type Chunk<A extends Array<unknown>, Split extends number, Temp extends Array<unknown> = [], R extends Array<unknown> = []> = 
  A extends [infer AF, ...infer AR]
    ? [...Temp, AF]['length'] extends Split
      ? Chunk<AR, Split, [], [...R, [...Temp, AF]]>
      : Chunk<AR, Split, [...Temp, AF], R>
    : Temp['length'] extends 0 ? R : [...R, Temp]

Solution by gangnamssal #35700

type Chunk< T extends any[], N , R extends any[] = [], I extends any[] = []> = 
  T extends [infer H, ... infer B] ? R['length'] extends N ?  Chunk<B,N,[H],[...I, R]>: Chunk<B,N,[...R,H],I> : R extends [] ? [...I,...R] : [...I,R]

Solution by Mohmn #35370

type Chunk<
  P extends any[],
  N extends number,
  A extends any[] = []
> = N extends keyof P
  ? N extends A['length']
    ? [A, ...Chunk<P, N>]
    : P extends [infer S, ...infer R]
    ? Chunk<R, N, [...A, S]>
    : [A] extends [[]]
    ? A
    : [A]
  : A

Solution by Keith-Web3 #35015

type Chunk<T extends any[], L extends number = 1, U extends any[] = []> = U['length'] extends L ? [U, ...Chunk<T, L>] :
T extends [infer R, ...infer rest] ? 
Chunk<rest, L, [...U, R]> : U extends [] ? U : [U]

Solution by ouzexi #34073

type Chunk<T extends any[],N extends number> =
T extends [] ? [] : // 1
T extends [infer L,infer M,...infer R] // 2
? L extends any[] // 3
? L['length'] extends N // 4
? [L,...Chunk<[M,...R],N>] // 5
: Chunk<[[...L,M],...R],N> // 6
: Chunk<[[L],...[M,...R]],N> // 7
: T[0] extends any[] // 8
?  T : [T] // 9

看了很多答案,似乎都是带了第二个参数的,其实没有必要。 逐行解释

T extends [] ? [] : 这句是为了判空 T extends [infer L,infer M,...infer R] 这句是关键,假设为了调整数组的大小,那么左边数组必须加入一个新参数,所以需要从右边借一个参数过来。那么问题来了 这个句子什么时候才会返回,看下面这个例子。

[1,2,3,4] extends  [infer L,infer M,...infer R] ? L | M | R : [] // 1 | 2 | [3,4]
[1,2,3] extends  [infer L,infer M,...infer R] ? L | M | R : [] // 1 | 2 | [3]
[1,2] extends  [infer L,infer M,...infer R] ? L | M | R  //2 | 1 | [] 说实在的这个联合类型顺序是怎么回事,我是一点都搞不懂,知道的大佬能说一下吗
[1] extends  [infer L,infer M,...infer R] ? L | M | R : [] // []

也就是说,只有当T参数大于一个的时候才会进入正确的通道。并获得参数L``M``R,然后来看这一句 L extends any[] 判断第一个参数是不是数组,如果不是说明是第一次进去,那么你就需要往L外面套上一层变成[L],所以需要第7行Chunk<[[L],...[M,...R]],N> // 7 。 当L是一个数组之后我们需要第4行 L['length'] extends N // 4来判断这个数组的长度是否等于N,不是的话就往左边加入新参数M继续遍历,也就是第6行: Chunk<[[...L,M],...R],N> // 6,如果说长度等于N的话,就可以进入下面的第5行了 [L,...Chunk<[M,...R],N>] // 5,继续往右遍历,直到T只剩下[最后一个参数],这时候数组不满足于第2行T extends [infer L,infer M,...infer R] // 2进入了第8行T[0] extends any[] // 8,判断第一个参数是不是数组,是的话就直接返回T,不是的话就往外面套一层变成[T]

不过笔者发现一个小bug就是了,你往里面放一个带数组的数组就会出现问题,如下

Chunk<[1, 2, [3, 4]], 2> // [[1, 2], [3, 4]]
Chunk<[1, 2, [3, 4]], 1> // [[1], [2], [3, 4]]

希望作者能完善一下样例和说明,毕竟上面这个不管怎么解释都有点说不太过去,我自己也不了解chunk的原理,所以也不知道这样划分对不对

Solution by xdrlmm #33957

// your answers
type Chunk<T extends any[], N extends number, Res extends any[] = [], C extends any[] = []> = 
  C['length'] extends N ? Chunk<T, N, [...Res, C]> : 
  T extends [infer A, ...infer R] ? Chunk<R, N, Res, [...C, A]> : C extends [] ? Res : [...Res, C]

Solution by heyuelan #33856

type Chunk<T extends any[], S extends number, Res extends any[] = [], Part extends any[] = [] > = 
 T extends [infer F, ...infer Rest] 
    ? S extends Part['length']
      ? Chunk<Rest, S, [...Res, Part], [F]>
      : Chunk<Rest, S, Res, [...Part, F]>
    : Res extends []
      ? Part extends []
        ? []
        : [Part]
      : [...Res, Part]

Solution by PiligrimStas #33752

type _Chunk<T extends any[], U extends number, R extends any[] = []> = T extends [infer F, ...infer rest]
  ? R['length'] extends U
    ? [R, ..._Chunk<rest, U, [F]>]
    : _Chunk<rest, U, [...R, F]>
  : [R]

type Chunk<T extends any[], U extends number> = T extends [] ? [] : _Chunk<T, U>

Solution by rimo030 #32886

// your answers
type Chunk<
	T extends any[],
	N extends number = 1,
	R extends any[] = [],
	C extends any[] = []
> = T extends [infer F, ...infer Rest]
	? C['length'] extends N
		? Chunk<Rest, N, [...R, C], [F]>
		: Chunk<Rest, N, R, [...C, F]>
	: [...R, ...(C['length'] extends 0 ? [] : [C])];

Solution by TRIS-H #31637

type Chunk<
  T extends any[],
  N extends number,
  Arr extends unknown[] = []
> = Arr["length"] extends N
  ? [Arr, ...Chunk<T, N>]
  : T extends [infer First, ...infer res]
  ? Chunk<res, N, [...Arr, First]>
  : Arr["length"] extends 0
  ? []
  : [Arr];

Solution by sunsunmonkey #31542

type NumberToArray<T extends number, U extends boolean[] = []> = 
  U['length'] extends T ?
  U :
  NumberToArray<T, [...U, true]>

type TakeFirst<T extends unknown[], S extends number, U extends unknown[] = []> = 
  U['length'] extends S ?
  U :
  T extends [infer F, ...infer Rest] ?
  TakeFirst<Rest, S, [...U, F]> :
  T

type PopFirst<T extends unknown[], S extends number, U extends unknown[] = []> = 
  U['length'] extends S ?
  T :
  T extends [infer _, ...infer Rest] ?
  PopFirst<Rest, S, [...U, true]> : 
  T

type WrapChunks<T extends unknown[], S extends number> = 
  PopFirst<T, S>['length'] extends 0 ?
  [T] :
  [TakeFirst<T, S>, ...Chunk<PopFirst<T, S>, S>]

type Chunk<T extends unknown[], S extends number> =
  T['length'] extends 0 ?
  [] :
  WrapChunks<T, S>

/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'

type cases = [
  Expect<Equal<Chunk<[], 1>, []>>,
  Expect<Equal<Chunk<[1, 2, 3], 1>, [[1], [2], [3]]>>,
  Expect<Equal<Chunk<[1, 2, 3], 2>, [[1, 2], [3]]>>,
  Expect<Equal<Chunk<[1, 2, 3, 4], 2>, [[1, 2], [3, 4]]>>,
  Expect<Equal<Chunk<[1, 2, 3, 4], 5>, [[1, 2, 3, 4]]>>,
  Expect<Equal<Chunk<[1, true, 2, false], 2>, [[1, true], [2, false]]>>,
]

Solution by gearonixx #30915

type Chunk<T extends unknown[], N extends number, C extends unknown[] = [], R extends unknown[] = []> = T extends [
  infer F,
  ...infer Rest,
]
  ? C['length'] extends N
    ? Chunk<Rest, N, [F], [...R, C]>
    : Chunk<Rest, N, [...C, F], [...R]>
  : [...R, C];

Solution by leejaehyup #30829

type Chunk<T extends readonly any[], N extends number, C extends any[] = [], R extends any[] = []> =
  C['length'] extends N
    ? Chunk<T, N, [], [...R, C]>
    : T extends [infer TF, ...infer TR]
      ? Chunk<TR, N, [...C, TF], R>
      : C extends []
        ? R
        : [...R, C]

Solution by matallui #30809

type Chunk<T extends any[], N extends number, C extends any[] = [], Result extends any[] = []> =
  C['length'] extends N
    ? Chunk<T, N, [], [...Result, C]>
    : T extends [infer F, ...infer Rest]
      ? Chunk<Rest, N, [...C, F], Result>
      : C extends []
        ? Result
        : [...Result, C]

Solution by jazelly #30452

// your answers,// 增加一个C记录chunk的结果
type Chunk<
	T extends unknown[],
	U extends number,
	C extends unknown[] = []
> = T extends [infer F, ...infer R]
	? Equal<C['length'], U> extends true
		? [C, ...Chunk<T, U, []>]
		: Chunk<R, U, [...C, F]>
	: C extends []
	? []
	: [C]

Solution by bebusy007 #30017

type Chunk<T extends any[], N extends number, A extends any[] = [], S extends any[] = []> =
  T extends [infer F, ...infer Rest]
    ? A['length'] extends N
      ? Chunk<Rest, N, [F], [...S, A]>
      : Chunk<Rest, N, [...A, F], S>
    : A['length'] extends 0 ? S : [...S, A]

Solution by hesoso #29841

type Chunk<
  Tuple extends unknown[],
  N extends number,
  Res extends unknown[] = [],
  Pack extends unknown[] = []
> = Tuple extends [infer Head, ...infer Tail]
  ? Pack["length"] extends N
    ? Chunk<Tail, N, [...Res, Pack], [Head]>
    : Chunk<Tail, N, Res, [...Pack, Head]>
  : Pack extends []
  ? Res
  : [...Res, Pack];

Solution by idebbarh #28842

type Pop<T extends any[], C extends number, S extends any[] = []> = S['length'] extends C
  ? S
  : T extends []
  ? S
  : T extends [infer First, ...infer Rest]
  ? Pop<Rest, C, [...S, First]>
  : never

type Chunk<T extends any[], C extends number> = T extends []
  ? T
  : T extends [...Pop<T, C>, ...infer Rest]
  ? [Pop<T, C>, ...Chunk<Rest, C>]
  : never;

Solution by JohnhanLiu #28768

type Chunk<
  T extends unknown[],
  Size extends number,
  Chunks extends unknown[] = [],
  Count extends unknown[] = [],
  Res extends unknown[] = []
> = Count["length"] extends Size
  ? Chunk<T, Size, [], [], [...Res, Chunks]>
  : T extends [infer F, ...infer R]
  ? Chunk<R, Size, [...Chunks, F], [...Count, unknown], Res>
  : Chunks["length"] extends 0
  ? Res
  : [...Res, Chunks];

Solution by DoubleWoodLin #28743

type Chunk<
  T extends readonly unknown[],
  N extends number = 1,
  Item extends unknown[] = [],
  Result extends unknown[] = []> = T extends [] ? Item extends [] ? Result : [...Result, Item] : T extends [infer Pre, ...infer Next]
    ? [...Item, Pre]['length'] extends N
        ? Chunk<Next, N, [], [...Result, [...Item, Pre]]>
        : Chunk<Next, N, [...Item, Pre], [...Result]>
    : Result

Solution by jiechliu #27701

type Chunk<
  T extends any[],
  Y extends number,
  N extends any[] = [],
  M extends any[] = []
> = T extends [infer F, ...(infer R)]
  ? N["length"] extends Y
    ? Chunk<T, Y, [], [...M, N]>
    : Chunk<R, Y, [...N, F], M>
  : N extends []
  ? M
  : [...M, N];

Solution by smileboyi #27075

type Chunk<T extends unknown[],num extends number,i extends unknown[] = [],arr extends unknown[][] = []> = T extends [] ? i extends [] ? arr : [...arr,i] : 
    T extends [infer A,...infer B] ?  
    i['length'] extends num ? Chunk<B,num,[A],[...arr,i]>:  
    Chunk<B,num,[...i,A],arr> : arr

Solution by WangZiChu199910252255 #26691

// your answers
type ChunkIter<A extends any[], L extends number, R extends any[] = []>
  = A extends [infer F, ...infer T] ?
    R['length'] extends L ? [R, ...ChunkIter<T, L, [F]>] : ChunkIter<T, L, [...R, F]>
    : [R]
type Chunk<A extends any[], L extends number> = A extends [] ? [] : ChunkIter<A, L>

Solution by adoin #26248

type Chunk<T extends unknown[], N extends number, R extends unknown[] = []> = T extends [infer First, ...infer Rest]
  ? R['length'] extends N
   ? [R, ...Chunk<Rest, N, [First]>]
   : [...Chunk<Rest, N, [...R, First]>]
  : R['length'] extends 0 ? [] : [R]

Solution by retkiewi #25914

// your answers
type FixLengthTuple<N extends number, A extends any[] = []> = 
  A['length'] extends N 
    ? A
    : FixLengthTuple<N, [...A, any]>



type Chunk<T extends any[], U extends number> = 
  T extends [...FixLengthTuple<U> , ...infer Rest] // 这样子 Rest 就空出了前面 U 个 Element
    ? T extends [...infer R, ...Rest] // R 就是前 U 个 Element 组成的 Array
      ? [R, ...Chunk<Rest, U>]
      : []
    : T extends [] 
      ? []
      : [T]

Solution by kiki-zjq #25299

type FixLengthTuple<N extends number, A extends any[] = []> = 
  A['length'] extends N 
    ? A
    : FixLengthTuple<N, [...A, any]>

type Chunk<T extends any[], U extends number> = 
  T extends [...FixLengthTuple<U> , ...infer Rest]
    ? T extends [...infer R, ...Rest]
      ? [R, ...Chunk<Rest, U>]
      : []
    : T extends [] 
      ? []
      : [T]

Solution by Minato1123 #25120

type Chunk<T extends unknown[], U extends number, Result extends unknown[] = []> = T extends [infer First, ...infer Rest]
? Result['length'] extends U
  ? [Result, ...Chunk<T, U>]
  : Chunk<Rest, U, [...Result, First]> 
: Result extends []
  ? Result
  : [Result]

Solution by NeylonR #25052