Search code examples
javascriptlodash

Best way to map this object into a new object


Using lodash or vanilla javascript, I need to convert this json:

{
  "results" : [
    {
        "values" : [
            {"label" : "FOO", "value"  : "foovalue" },
            {"label" : "BAR", "value" : "barvalue1" },
            {"label" : "BAR", "value" : "barvalue2" }
        ]
    },
    {
        "values" : [
            {"label" : "FOO", "value"  : "foovalue"},
            {"label" : "BAR", "value" : "barvalue1"},
            {"label" : "BAR", "value" : "barvalue2"}
        ]
   }
    ]
}

into a new object where the label values become the key and duplicates are made into an array of new objects like this:

[
    [{"FOO" : "foovalue", "BAR" : ["barvalue1", "barvalue2"]}], 
    [{"FOO" : "foovalue", "BAR" : ["barvalue1", "barvalue2"]}]
]

I've tried using _.map but it is overwriting the duplicate values and I need them all in an array.

Here is the closest I've come:

var arr = _.map(results, function(o) {
    return _.map(o.values, function(v) {
        var obj = {};
        obj[t.label] = t.value;
        return obj;
    });
});

where arr returns an array of the objects like this (with the objects being overwritten and not combined into a single object) [{"FOO" : "foovalue"},{"BAR" : "barvalue2"}] and I'm stuck trying to make them into the above array.


Solution

  • You could map the outer array and reduce the inner array by collecting the values of labels. If more than one collected element use an array.

    var results = [{ values: [{ label: "FOO", value: "foovalue" }, { label: "BAR", value: "barvalue1" }, { label: "BAR", value: "barvalue2" }] }, { values: [{ label: "FOO", value: "foovalue" }, { label: "BAR", value: "barvalue1" }, { label: "BAR", value: "barvalue2" }] }],
        grouped = results.map(({ values }) => [
            values.reduce((o, { label, value }) => {
                if (!o[label]) {
                    o[label] = value;
                    return o;
                }
                if (!Array.isArray(o[label])) {
                    o[label] = [o[label]];
                }
                o[label].push(value);
                return o;
            }, {})
        ]);
        
    console.log(grouped);
    .as-console-wrapper { max-height: 100% !important; top: 0; }