1

I am using d3-array rollup to do group-by like counting operation, in preparation to generate an html table.

I have a variable number of grouping keys, which I am passing like this:

var rollup_keys = new Map([
        ['count', v => v.length],
        ['codeversion', d => d.codeversion],
        ['mode', d => d.mode],
        ['status', d => d.status]])

    var data_counts = d3.rollup(all_data, ...rollup_keys.values())

That gives me nested Maps, e.g. pseudo-representation,

Map(3) {"codeversion_1" => 
    Map(1) {"mode_1" => 
        Map(2) {"status_1" => count_1,
                "status_2" => count_2},
       "codeversion_2" =>
    Map(1) {"mode_1" =>
        Map(2) {"status_1" => count_1,
                "status_2" => count_2}
    [...truncated...]
}             

I use Vue.js for-loops to render the html table, which means it's easiest to have a flat representation of the above nested map. Something like::

[
    ["codeversion_1", "mode_1", "status_1", 1"],
    ["codeversion_1", "mode_1", "status_2", 49],
    ["codeversion_2", "mode_1", "status_1", 3],
    ["codeversion_2", "mode_1", "status_2", 7],
]

To convert the nested maps into the above flat list format, I am using this recursive approach:

flatten_data: function(flatten_me){
                let rows = []
                if ( flatten_me instanceof Map) {
                    for (let [key, value] of flatten_me.entries()) {
                        if (value instanceof Map) {
                            let _rows = this.flatten_data(value)
                            for (_row of _rows) {
                                rows.push([key].concat(_row))
                            }
                        } else {
                            rows.push([key, value])
                        }
                    }
                }
                return rows
            }

But is there something native to d3-array that would mean I wouldn't have to flatten it myself? I feel like I'm missing something obvious, but searches for flatten array don't seem to give the full key-value permutation I'm seeking.

deargle
  • 487
  • 4
  • 8

1 Answers1

0

It's hard to test the code without some sample data, but I'd recommend using Array.reduce(). Here's a two-criteria example.

const aggregator = (agg, cur) => agg.concat(
  Array.from(cur[1]).map(sportCount =>
    [cur[0]].concat(statusCount)
  )
);

const rolled = d3.rollup(athletes, v => v.length, d => d.mode, d => d.status);
const flattened = Array.from(rolled).reduce(aggregator, []);
carpiediem
  • 1,918
  • 22
  • 41