lodashパーティション方式の再作成
21870 ワード
Lodash _.partition 関数は、配列を 2 つのグループに分割します.1 つは指定された条件を満たしている項目で満たされ、もう 1 つのグループは満たされていない項目で満たされています.
このブログ記事の目的は、パーティションの方法を複製することですが、いくつかの変更を加えて、いくつかの追加機能を追加することです.概念は同じままですが、1 つの述語を取る代わりに、関数は述語の配列 (パーティション関数) を取り、それらに基づいて与えられた配列を分割することができます.
Typescript の関数シグネチャは次のようになります
使用例は、配列を 2 つの配列に分割することです.一方には 5 より大きい数値が含まれ、もう一方には 5 以下の項目が含まれます.
パーティション カウントが predicates 配列の長さに等しいことがわかります.最初のアサーションを記述し、それを通過させるコードを実装しましょう.
2 つの述語を渡すことは、結果の配列にも 2 つのパーティションが含まれている必要があることを意味します.
この関数は、述語配列の長さと同じ長さの配列の配列を作成します.
次のステップは、ロジックを適用する述語を実装することです.アイデアは、述語が項目に対して true を返すたびに、後者がその述語インデックスでパーティション配列に追加されるということです.
述語インデックスを見つけるには、指定された条件を満たす最初のアイテムのインデックスを返す .findIndex 関数を使用するか、何も見つからない場合は -1 を返します.
機能を実装する前にテストを書きましょう.
前述のように、要素ごとに、それが満たす述語を見つけようとします.見つかった場合は、results[predicateIndex].push(item); を使用して対応する述語インデックスに追加します.
ソリューションは、条件を満たさないすべてのアイテムを無視するようになりました.ただし、元の lodash _.partition 関数は配列を 2 つのグループに分割します.一方には条件を満たす要素が含まれ、もう一方には満たされない要素が含まれます.
それでは実装してみましょうが、まずはいつものようにロジックを実装する前にテストを書きます.
ここには 2 つの条件があります.数値であり、5 未満または 5 を超えるアイテムのみを取得します.残りのアイテムは、パーティション配列の末尾にある配列に追加する必要があります.最初に、偽のアイテムを含むこの配列を結果配列に追加しましょう.
項目が指定された述語の少なくとも 1 つを満たさない場合は常に、インデックスが結果配列の最後にある配列に追加されます.アルゴリズムは次のようになります.以前のテストも適切にリファクタリングする必要があります.
結果配列の末尾に偽の項目配列が追加されるため、そのインデックスは predicates.length になります.
これで、partitionWith 関数は、述語が 1 つだけ提供された場合、lodash の partition とまったく同じように動作し、偽の要素を結果配列の末尾にある別の配列に保持します.
テストスイートを含むフルバージョンはここにあります
https://codesandbox.io/s/awesome-almeida-b7hyp?file=/src/index.ts
詳細については、Twitter でフォローしてください
このブログ記事の目的は、パーティションの方法を複製することですが、いくつかの変更を加えて、いくつかの追加機能を追加することです.概念は同じままですが、1 つの述語を取る代わりに、関数は述語の配列 (パーティション関数) を取り、それらに基づいて与えられた配列を分割することができます.
Typescript の関数シグネチャは次のようになります
type PartitionWith = <T>(items: T[], predicates: ((item: T) => boolean)[]): T[][]
使用例は、配列を 2 つの配列に分割することです.一方には 5 より大きい数値が含まれ、もう一方には 5 以下の項目が含まれます.
const array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const isLessOrEqualThanFive = (number: number) => number <= 5;
const isGreaterThanFive = (number) => number > 5;
const results = partitionWith(array, [isLessOrEqualThanFive, isGreaterThanFive ]);
console.log(results); // [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9, 10]]
パーティション カウントが predicates 配列の長さに等しいことがわかります.最初のアサーションを記述し、それを通過させるコードを実装しましょう.
it('creates an array of partitions with a length that is equal to the predicates array length', () => {
const predicateOne = (n: number) => n < 5;
const predicateTwo = (n: number) => n >= 5;
const array = [1, 2, 4, 5, 6];
const results = partitionWith(array, [predicateOne, predicateTwo]);
expect(results.length).toBe(2);
})
2 つの述語を渡すことは、結果の配列にも 2 つのパーティションが含まれている必要があることを意味します.
const partitionWith: PartitionWith = <T>(items: T[], predicates: ((item: T) => boolean)[]) => {
const results: T[][] = [...Array(predicates.length)].map(x => []);
return results;
}
この関数は、述語配列の長さと同じ長さの配列の配列を作成します.
次のステップは、ロジックを適用する述語を実装することです.アイデアは、述語が項目に対して true を返すたびに、後者がその述語インデックスでパーティション配列に追加されるということです.
述語インデックスを見つけるには、指定された条件を満たす最初のアイテムのインデックスを返す .findIndex 関数を使用するか、何も見つからない場合は -1 を返します.
const predicateIndex = predicates.findIndex(predicate => predicate(item));
機能を実装する前にテストを書きましょう.
it('create partitions based on the provided predicates', () => {
const arrayToPartition = [0, 1, '1', 2, 3, 4, '12', 5, 6, 7, 8, 9, , '11', 10];
const isLessThanFive = (maybeNumber: number | string) => typeof maybeNumber === 'number' && maybeNumber < 5;
const isGreaterOrEqualThanFive = (maybeNumber: number | string) => typeof maybeNumber === 'number' && maybeNumber >= 5;
const isString = (maybeString: number | string) => typeof maybeString === 'string';
const results = partitionWith(arrayToPartition, [isLessThanFive, isGreaterOrEqualThanFive, isString]);
expect(results).toEqual([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9, 10], ['1', '12', '11']]);
});
type PartitionWith = <T>(items: T[], predicates: ((item: T) => boolean)[]) => T[][];
export const partitionWith: PartitionWith = <T>(items: T[], predicates: ((item: T) => boolean)[]) => {
const results: T[][] = [...Array(predicates.length)].map(x => []);
items.forEach((item) => {
const predicateIndex = predicates.findIndex(predicate => predicate(item));
if(predicateIndex !== -1) {
results[predicateIndex].push(item);
}
})
return results;
}
前述のように、要素ごとに、それが満たす述語を見つけようとします.見つかった場合は、results[predicateIndex].push(item); を使用して対応する述語インデックスに追加します.
ソリューションは、条件を満たさないすべてのアイテムを無視するようになりました.ただし、元の lodash _.partition 関数は配列を 2 つのグループに分割します.一方には条件を満たす要素が含まれ、もう一方には満たされない要素が含まれます.
それでは実装してみましょうが、まずはいつものようにロジックを実装する前にテストを書きます.
it('returns an extra array of items that did not satisfy any condition', () => {
const items = [0, 1, '1', 2, 3, 4, '12', 5, 6, 7, 8, 9, , '11', 10];
const isLessThanFive = (maybeNumber: number | string) => typeof maybeNumber === 'number' && maybeNumber < 5;
const isGreaterOrEqualThanFive = (maybeNumber: number | string) => typeof maybeNumber === 'number' && maybeNumber >= 5;
const results = partitionWith(items, [isLessThanFive, isGreaterOrEqualThanFive]);
expect(results).toEqual([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9, 10], ['1', '12', '11']])
})
ここには 2 つの条件があります.数値であり、5 未満または 5 を超えるアイテムのみを取得します.残りのアイテムは、パーティション配列の末尾にある配列に追加する必要があります.最初に、偽のアイテムを含むこの配列を結果配列に追加しましょう.
results.push([])
項目が指定された述語の少なくとも 1 つを満たさない場合は常に、インデックスが結果配列の最後にある配列に追加されます.アルゴリズムは次のようになります.以前のテストも適切にリファクタリングする必要があります.
export const partitionWith: PartitionWith = <T>(items: T[], predicates: ((item: T) => boolean)[]) => {
const results: T[][] = [...Array(predicates.length)].map(x => []);
results.push([])
items.forEach((item) => {
const predicateIndex = predicates.findIndex(predicate => predicate(item));
if(predicateIndex !== -1) {
results[predicateIndex].push(item);
} else {
const falsyResultsArrayIndex = predicates.length;
results[falsyResultsArrayIndex].push(item);
}
})
return results;
}
結果配列の末尾に偽の項目配列が追加されるため、そのインデックスは predicates.length になります.
これで、partitionWith 関数は、述語が 1 つだけ提供された場合、lodash の partition とまったく同じように動作し、偽の要素を結果配列の末尾にある別の配列に保持します.
テストスイートを含むフルバージョンはここにあります
https://codesandbox.io/s/awesome-almeida-b7hyp?file=/src/index.ts
詳細については、Twitter でフォローしてください
Reference
この問題について(lodashパーティション方式の再作成), 我々は、より多くの情報をここで見つけました https://dev.to/_ab_del_/recreating-lodash-partition-method-3a31テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol