From 4f33c0c6942ac78b60733a88f0273fa41ab41184 Mon Sep 17 00:00:00 2001 From: ayame113 <40050810+ayame113@users.noreply.github.com> Date: Mon, 13 Sep 2021 03:51:28 +0900 Subject: [PATCH 1/4] feat (collections): add `runningReduce` --- collections/README.md | 18 +++++++++++++ collections/mod.ts | 1 + collections/running_reduce.ts | 27 +++++++++++++++++++ collections/running_reduce_test.ts | 43 ++++++++++++++++++++++++++++++ 4 files changed, 89 insertions(+) create mode 100644 collections/running_reduce.ts create mode 100644 collections/running_reduce_test.ts diff --git a/collections/README.md b/collections/README.md index 8bc2fd9b7fd1..5ac6fcce5bbf 100644 --- a/collections/README.md +++ b/collections/README.md @@ -834,3 +834,21 @@ const random = sample(numbers); assert(numbers.includes(random as number)); ``` + +### runningReduce + +Calls the given reducer on each element of the given collection, passing it's +result as the accumulator to the next respective call, starting with the given +initialValue. Returns all intermediate accumulator results. + +Example: + +```ts +import { runningReduce } from "https://deno.land/std@$STD_VERSION/collections/mod.ts"; +import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; + +const numbers = [1, 2, 3, 4, 5]; +const sumSteps = runningReduce(numbers, (sum, current) => sum + current, 0); + +assertEquals(sumSteps, [1, 3, 6, 10, 15]); +``` diff --git a/collections/mod.ts b/collections/mod.ts index 0e6acbdc8f30..e1cc1cdf7d98 100644 --- a/collections/mod.ts +++ b/collections/mod.ts @@ -41,3 +41,4 @@ export * from "./first_not_nullish_of.ts"; export * from "./drop_last_while.ts"; export * from "./reduce_groups.ts"; export * from "./sample.ts"; +export * from "./running_reduce.ts"; diff --git a/collections/running_reduce.ts b/collections/running_reduce.ts new file mode 100644 index 000000000000..aa6b9bba22bc --- /dev/null +++ b/collections/running_reduce.ts @@ -0,0 +1,27 @@ +// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. + +/** + * Calls the given reducer on each element of the given collection, passing it's + * result as the accumulator to the next respective call, starting with the given + * initialValue. Returns all intermediate accumulator results. + * + * Example: + * + * ```ts + * import { runningReduce } from "https://deno.land/std@$STD_VERSION/collections/mod.ts"; + * import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; + * + * const numbers = [1, 2, 3, 4, 5]; + * const sumSteps = runningReduce(numbers, (sum, current) => sum + current, 0); + * + * assertEquals(sumSteps, [1, 3, 6, 10, 15]); + * ``` + */ +export function runningReduce( + collection: readonly T[], + reducer: (accumulator: A, current: T) => A, + initialValue: A, +): A[] { + let _initialValue = initialValue; + return collection.map((el) => _initialValue = reducer(_initialValue, el)); +} diff --git a/collections/running_reduce_test.ts b/collections/running_reduce_test.ts new file mode 100644 index 000000000000..1c9550981b28 --- /dev/null +++ b/collections/running_reduce_test.ts @@ -0,0 +1,43 @@ +// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. + +import { assertEquals } from "../testing/asserts.ts"; +import { runningReduce } from "./running_reduce.ts"; + +Deno.test({ + name: "[collections/runningReduce] no mutation", + fn() { + const numbers = [1, 2, 3, 4, 5]; + runningReduce(numbers, (sum, current) => sum + current, 0); + + assertEquals(numbers, [1, 2, 3, 4, 5]); + }, +}); + +Deno.test({ + name: "[collections/runningReduce] array of numbers", + fn() { + const numbers = [1, 2, 3, 4, 5]; + const result = runningReduce(numbers, (sum, current) => sum + current, 0); + + assertEquals(result, [1, 3, 6, 10, 15]); + }, +}); + +Deno.test({ + name: "[collections/runningReduce] array of strings", + fn() { + const strings = ["a", "b", "c", "d", "e"]; + const result = runningReduce(strings, (str, current) => str + current, ""); + + assertEquals(result, ["a", "ab", "abc", "abcd", "abcde"]); + }, +}); + +Deno.test({ + name: "[collections/runningReduce] empty input", + fn() { + const result = runningReduce([], (sum, current) => sum + current, 0); + + assertEquals(result, []); + }, +}); From df5a0513683c26d59203f4f6c74db58f21b13b40 Mon Sep 17 00:00:00 2001 From: ayame113 <40050810+ayame113@users.noreply.github.com> Date: Mon, 13 Sep 2021 04:44:48 +0900 Subject: [PATCH 2/4] use `array` instead of `collection` --- collections/running_reduce.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/collections/running_reduce.ts b/collections/running_reduce.ts index aa6b9bba22bc..c7db7ac999e1 100644 --- a/collections/running_reduce.ts +++ b/collections/running_reduce.ts @@ -18,10 +18,10 @@ * ``` */ export function runningReduce( - collection: readonly T[], + array: readonly T[], reducer: (accumulator: A, current: T) => A, initialValue: A, ): A[] { let _initialValue = initialValue; - return collection.map((el) => _initialValue = reducer(_initialValue, el)); + return array.map((el) => _initialValue = reducer(_initialValue, el)); } From ad213195dc53b484135821f6a88406c03805953f Mon Sep 17 00:00:00 2001 From: ayame113 <40050810+ayame113@users.noreply.github.com> Date: Mon, 13 Sep 2021 04:47:58 +0900 Subject: [PATCH 3/4] use `O` instead of `A` in type name --- collections/running_reduce.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/collections/running_reduce.ts b/collections/running_reduce.ts index c7db7ac999e1..b1c224225ede 100644 --- a/collections/running_reduce.ts +++ b/collections/running_reduce.ts @@ -17,11 +17,11 @@ * assertEquals(sumSteps, [1, 3, 6, 10, 15]); * ``` */ -export function runningReduce( +export function runningReduce( array: readonly T[], - reducer: (accumulator: A, current: T) => A, - initialValue: A, -): A[] { + reducer: (accumulator: O, current: T) => O, + initialValue: O, +): O[] { let _initialValue = initialValue; return array.map((el) => _initialValue = reducer(_initialValue, el)); } From 87273ca9287a9effd4f34eee1c335a3a3d14b7df Mon Sep 17 00:00:00 2001 From: ayame113 <40050810+ayame113@users.noreply.github.com> Date: Mon, 13 Sep 2021 04:53:00 +0900 Subject: [PATCH 4/4] rename `_initialValue` to `currentResult` --- collections/running_reduce.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/collections/running_reduce.ts b/collections/running_reduce.ts index b1c224225ede..24995dee2049 100644 --- a/collections/running_reduce.ts +++ b/collections/running_reduce.ts @@ -22,6 +22,6 @@ export function runningReduce( reducer: (accumulator: O, current: T) => O, initialValue: O, ): O[] { - let _initialValue = initialValue; - return array.map((el) => _initialValue = reducer(_initialValue, el)); + let currentResult = initialValue; + return array.map((el) => currentResult = reducer(currentResult, el)); }