0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

文字列配列を任意の並び順で辞書式ソートした型を取得する方法

Posted at

※配列をソートした結果 ではなく 含まれている型をソートした結果を取得する方法です。
やりたいことの前準備で必要だったので、備忘録です。


// この型に文字列リテラルの配列を渡すと、ソートした結果の配列型を返す
type Sort<T extends string[]> = Joins<SortImpl<Separators<T>>>;

type Test = Sort<['AB', 'G', 'AE', 'G', 'BD', '2F', 'AC', 'B', '1F']>; 
//=> type Test = ["AB", "AC", "AE", "B", "BD", "G", "G", "1F", "2F"]


// 対象となる文字とその並び順
type Characters = [
    'A', 'B', 'C', 'D', 'E',
    'F', 'G', 'H', 'I', 'J',
    'K', 'L', 'M', 'N', 'O',
    'P', 'Q', 'R', 'S', 'T',
    'U', 'V', 'W', 'X', 'Y',
    'Z',
    0, 1, 2, 3, 4,
    5, 6, 7, 8, 9,
];

type Character = Characters[number];

// ソートするために文字列を文字単位に区切る
type Separator<T extends string> = T extends `${infer A extends Character}${infer B}` ? [A, ...Separator<B> ]  : [];
type Separators<T extends string[]> = T extends [infer A extends string, ...infer B extends string[]] ? [Separator<A>, ...Separators<B>]: [];
// 区切った文字の復元用
type Join<T extends Character[]> = T extends [infer A extends Character, ...infer B extends Character[]] ? `${A}${Join<B>}` : '';
type Joins<T extends (Character[] | undefined)[]> = T extends [infer A extends Character[], ...infer B extends Character[][]] ? [Join<A>, ...Joins<B>] : [];

type Pop<T extends Character[]> = T extends [T[0], ...infer A] ? A : [];

// 対象となる文字を先頭から比較していき、どちらかがマッチするか調べる。
// どちらも引っかからない場合、次の対象文字で比較する。
// 同じ文字同士の場合、次の文字同士で比較する。
type Compare<T1 extends Character[], T2 extends Character[], C extends Character[] = Characters> =
    T1[0] extends T2[0] 
        ? [T1[0], T2[0]] extends [undefined, undefined]
            ? 0
            : Compare<Pop<T1>, Pop<T2>>
        : T1[0] extends undefined
            ? -1
            : T2[0] extends undefined
                ? 1
                : T1[0] extends C[0] 
                    ? -1
                    : T2[0] extends C[0]
                        ? 1
                        : Compare<T1, T2, Pop<C>>; 

// マージソートを行う
type Merge<T1 extends Character[][], T2 extends Character[][]> =
    T1[0] extends undefined 
        ? [...T2]
        : T2[0] extends undefined
            ? [...T1]
            : Compare<T1[0], T2[0]> extends -1 
                ? T1 extends [infer A extends Character[], ...infer B extends Character[][]]
                    ? [A, ...Merge<B, T2>] 
                    : []
                : T2 extends [infer A extends Character[], ... infer B extends Character[][]]
                    ? [A, ...Merge<T1, B>]
                    : []
;

type SortImpl<T extends Character[][]> =
    T[1] extends undefined 
        ? [T[0]] 
        : T extends [infer A extends Character[], ...infer B extends Character[][]]
        ? Merge<[A], SortImpl<B>>
        : [];
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?