From 53e12d22414c40aa2fc61fd8d1d2352f30b4a89e Mon Sep 17 00:00:00 2001 From: rodmoioliveira Date: Wed, 20 May 2020 11:48:13 -0300 Subject: [PATCH 1/2] add snippet partitionBy --- snippets/partitionBy.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 snippets/partitionBy.md diff --git a/snippets/partitionBy.md b/snippets/partitionBy.md new file mode 100644 index 000000000..de6bd3cd4 --- /dev/null +++ b/snippets/partitionBy.md @@ -0,0 +1,34 @@ +--- +title: partitionBy +tags: array,object,function,intermediate +--- + +Applies `fn` to each value in `arr`, splitting it each time `fn` returns a new value. + +Use `Array.prototype.reduce()` and `Array.prototype.push()` to create the start index of each partition. +Use `Array.prototype.map()` to create the slice interval of each partition. +Use `Array.prototype.slice()` to create each partition. + +```js +const partitionBy = (arr, fn) => + arr + .reduce((acc, val, i, a) => { + acc.push(fn(val, i, a)); + return acc; + }, []) + .reduce((acc, val, i, a) => { + if (val !== a[i + 1]) { + acc.push(i + 1); + } + return acc; + }, []) + .map((interval, i, a) => + i === 0 ? arr.slice(...[0, interval]) : arr.slice(...[a[i - 1], interval]) + ); +``` + +```js +const numbers = [1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 5]; +partitionBy(numbers, n => n % 2 === 0); // = > [ [ 1, 1, 1, 1, 1, 3, 3, 3, 3, 3 ], [ 4 ], [ 5, 5, 5, 5, 5 ] ] +partitionBy(numbers, n => n); // => [ [ 1, 1, 1, 1, 1 ], [ 3, 3, 3, 3, 3 ], [ 4 ], [ 5, 5, 5, 5, 5 ] ] +``` From 1f25d57f60f5f5f3961568cbc8ecec0bf6f983bf Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Wed, 20 May 2020 19:00:29 +0300 Subject: [PATCH 2/2] Increase performance for partitionBy --- snippets/partitionBy.md | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/snippets/partitionBy.md b/snippets/partitionBy.md index de6bd3cd4..ea6824cbc 100644 --- a/snippets/partitionBy.md +++ b/snippets/partitionBy.md @@ -1,34 +1,28 @@ --- title: partitionBy -tags: array,object,function,intermediate +tags: array,object,function,advanced --- Applies `fn` to each value in `arr`, splitting it each time `fn` returns a new value. -Use `Array.prototype.reduce()` and `Array.prototype.push()` to create the start index of each partition. -Use `Array.prototype.map()` to create the slice interval of each partition. -Use `Array.prototype.slice()` to create each partition. +Use `Array.prototype.reduce()` with an accumulator object that will hold the resulting array and the last value returned from `fn`. +Use `Array.prototype.push()` to add each value in `arr` to the appropriate partition in the accumulator array. ```js const partitionBy = (arr, fn) => - arr - .reduce((acc, val, i, a) => { - acc.push(fn(val, i, a)); - return acc; - }, []) - .reduce((acc, val, i, a) => { - if (val !== a[i + 1]) { - acc.push(i + 1); - } - return acc; - }, []) - .map((interval, i, a) => - i === 0 ? arr.slice(...[0, interval]) : arr.slice(...[a[i - 1], interval]) - ); + arr.reduce( + ({ res, last }, v, i, a) => { + const next = fn(v, i, a); + if (next !== last) res.push([v]); + else res[res.length - 1].push(v); + return { res, last: next }; + }, + { res: [] } + ).res; ``` ```js -const numbers = [1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 5]; -partitionBy(numbers, n => n % 2 === 0); // = > [ [ 1, 1, 1, 1, 1, 3, 3, 3, 3, 3 ], [ 4 ], [ 5, 5, 5, 5, 5 ] ] -partitionBy(numbers, n => n); // => [ [ 1, 1, 1, 1, 1 ], [ 3, 3, 3, 3, 3 ], [ 4 ], [ 5, 5, 5, 5, 5 ] ] +const numbers = [1, 1, 3, 3, 4, 5, 5, 5]; +partitionBy(numbers, n => n % 2 === 0); // [[1, 1, 3, 3], [4], [5, 5, 5]] +partitionBy(numbers, n => n); // [[1, 1], [3, 3], [4], [5, 5, 5]] ```