diff --git a/README.md b/README.md index 3a1b0dad..826f1425 100644 --- a/README.md +++ b/README.md @@ -417,6 +417,10 @@ This produces: Equivalent to [group](#group), but returns nested arrays instead of nested maps. +# d3.flatGroup(iterable, ...keys) · [Source](https://github.com/d3/d3-array/blob/master/src/group.js), [Examples](https://observablehq.com/@d3/d3-flatgroup) + +Equivalent to [group](#group), but returns a flat array of [*key0*, *key1*, …, *values*] instead of nested maps. + # d3.index(iterable, ...keys) · [Source](https://github.com/d3/d3-array/blob/master/src/group.js), [Examples](https://observablehq.com/@d3/d3-group) Equivalent to [group](#group) but returns a unique value per compound key instead of an array, throwing if the key is not unique. @@ -507,6 +511,10 @@ To convert a Map to an Array, use [Array.from](https://developer.mozilla.org/en- Equivalent to [rollup](#rollup), but returns nested arrays instead of nested maps. +# d3.flatRollup(iterable, ...keys) · [Source](https://github.com/d3/d3-array/blob/master/src/group.js), [Examples](https://observablehq.com/@d3/d3-flatgroup) + +Equivalent to [rollup](#rollup), but returns a flat array of [*key0*, *key1*, …, *value*] instead of nested maps. + # d3.groupSort(iterable, comparator, key) · [Source](https://github.com/d3/d3-array/blob/master/src/groupSort.js), [Examples](https://observablehq.com/@d3/d3-groupsort)
# d3.groupSort(iterable, accessor, key) diff --git a/src/group.js b/src/group.js index 77ae4dc7..0c30d7e9 100644 --- a/src/group.js +++ b/src/group.js @@ -9,6 +9,21 @@ export function groups(values, ...keys) { return nest(values, Array.from, identity, keys); } +function flatten(groups, keys) { + for (let i = 1, n = keys.length; i < n; ++i) { + groups = groups.flatMap(g => g.pop().map(([key, value]) => [...g, key, value])); + } + return groups; +} + +export function flatGroup(values, ...keys) { + return flatten(groups(values, ...keys), keys); +} + +export function flatRollup(values, reduce, ...keys) { + return flatten(rollups(values, reduce, ...keys), keys); +} + export function rollup(values, reduce, ...keys) { return nest(values, identity, reduce, keys); } diff --git a/src/index.js b/src/index.js index 44c5ac66..209d7b2f 100644 --- a/src/index.js +++ b/src/index.js @@ -8,7 +8,7 @@ export {default as descending} from "./descending.js"; export {default as deviation} from "./deviation.js"; export {default as extent} from "./extent.js"; export {Adder, fsum, fcumsum} from "./fsum.js"; -export {default as group, groups, index, indexes, rollup, rollups} from "./group.js"; +export {default as group, flatGroup, flatRollup, groups, index, indexes, rollup, rollups} from "./group.js"; export {default as groupSort} from "./groupSort.js"; export {default as bin, default as histogram} from "./bin.js"; // Deprecated; use bin. export {default as thresholdFreedmanDiaconis} from "./threshold/freedmanDiaconis.js"; diff --git a/test/flatGroup-test.js b/test/flatGroup-test.js new file mode 100644 index 00000000..959d3771 --- /dev/null +++ b/test/flatGroup-test.js @@ -0,0 +1,21 @@ +import assert from "assert"; +import {flatGroup} from "../src/index.js"; + +const data = [ + {name: "jim", amount: "34.0", date: "11/12/2015"}, + {name: "carl", amount: "120.11", date: "11/12/2015"}, + {name: "stacy", amount: "12.01", date: "01/04/2016"}, + {name: "stacy", amount: "34.05", date: "01/04/2016"} +]; + +it("flatGroup(data, accessor, accessor) returns the expected array", () => { + assert.deepStrictEqual( + flatGroup(data, d => d.name, d => d.amount), + [ + ['jim', '34.0', [{name: 'jim', amount: '34.0', date: '11/12/2015'}]], + ['carl', '120.11', [{name: 'carl', amount: '120.11', date: '11/12/2015'}]], + ['stacy', '12.01', [{name: 'stacy', amount: '12.01', date: '01/04/2016'}]], + ['stacy', '34.05', [{name: 'stacy', amount: '34.05', date: '01/04/2016'}]] + ] + ); +}); diff --git a/test/flatRollup-test.js b/test/flatRollup-test.js new file mode 100644 index 00000000..04b05496 --- /dev/null +++ b/test/flatRollup-test.js @@ -0,0 +1,32 @@ +import assert from "assert"; +import {flatRollup} from "../src/index.js"; + +const data = [ + {name: "jim", amount: "34.0", date: "11/12/2015"}, + {name: "carl", amount: "120.11", date: "11/12/2015"}, + {name: "stacy", amount: "12.01", date: "01/04/2016"}, + {name: "stacy", amount: "34.05", date: "01/04/2016"} +]; + +it("flatRollup(data, reduce, accessor) returns the expected array", () => { + assert.deepStrictEqual( + flatRollup(data, v => v.length, d => d.name), + [ + ['jim', 1], + ['carl', 1], + ['stacy', 2] + ] + ); +}); + +it("flatRollup(data, reduce, accessor, accessor) returns the expected array", () => { + assert.deepStrictEqual( + flatRollup(data, v => v.length, d => d.name, d => d.amount), + [ + ['jim', '34.0', 1], + ['carl', '120.11', 1], + ['stacy', '12.01', 1], + ['stacy', '34.05', 1] + ] + ); +});