🏠 back to Observable

from d3.group to a map with merged keys

Is there a way to get a map with merged keys from a map of map, or from a map of map of map.

I’ve been playing with d3.group(iterable, d=> d.key1, d=>key2), (merci @Fil for this d3-group notebook )
my above d3.group(... produce a map like

{
    "foo" => {"Mon" => [obj1, obj2],
	      "Wed" => [obj3]},
    "baz" => {"Tue" => [obj4, obj5, obj6],
	      "Wed" => [obj7, obj8]},
 ...
}

Nice!
But then how do I flatten it so I get this

{
    "foo-Mon" => [obj1, obj2],
    "foo-Wed" => [obj3],
    "baz-Tue" => [obj4, obj5, obj6],
    "baz-Wed" => [obj7, obj8]
    ...
}

I made this function to do the job

function upliftkey(res, [k, arr]) {
  return  arr.reduce((acc, [nk,  nv]) => Object.assign(res, ({[`${k}-${nk}`]: nv})), {})
}

That I use in a reduce like so d3-array.groups(data, d=>d.key1, d=>d.key2).reduce(upliftkey, {}) . It’s ok, but my recursive attempt to flatten an aribtray number of nested group has fail.

So my question. Is it already in d3 ? and if not do you think it could be included ?

1 Like

array.flat and array.flatMap, two recent additions to JavaScript, are very useful for this sort of thing. (And they can be combined with Array.from to flatten iterables such as maps.)

But the simplest thing in this case would be to change the key for d3.group,

d3.group(iterable, d => `${d.key1}-${d.key2}`)

which would generate the desired structure directly.

3 Likes

Excellent. Thank you. I love it when something I think hard becomes easy. :o)

3 Likes