Collapse an array of objects by property value in javascript

As a collapse and an array for a property to handle:

[ { key: 'black', value: [ '2', '3', '9' ] },
  { key: 'black', value: [ '1' ] },
  { key: 'gold', value: [ '2', '3' ] },
  { key: 'gold', value: [ '1' ] },
  { key: 'red', value: [ '9' ] },
  { key: 'white', value: [ '2', '3' ] },
  { key: 'white', value: [ '1' ] } ]

... at:

[ { key: 'black', value: [ '1', '2', '3', '9' ] },
  { key: 'gold', value: [ '1', '2', '3' ] },
  { key: 'red', value: [ '9' ] },
  { key: 'white', value: [ '1', '2', '3' ] } ]

... with javascript.

I feel that there should be a fairly simple way to do this using lodash or Array.reduce, but I cannot have my life determine how to do it.

+4
source share
4 answers

You can use a temporary object to refer to groups and return an array with the result in one loop.

var array = [{ key: 'black', value: ['2', '3', '9'] }, { key: 'black', value: ['1'] }, { key: 'gold', value: ['2', '3'] }, { key: 'gold', value: ['1'] }, { key: 'red', value: ['9'] }, { key: 'white', value: ['2', '3'] }, { key: 'white', value: ['1'] }],
    result = [];

array.forEach(function (a) {
    if (!this[a.key]) {
        this[a.key] = { key: a.key, value: [] };
        result.push(this[a.key]);
    }
    this[a.key].value = this[a.key].value.concat(a.value);
    this[a.key].value.sort();
}, {});

document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
Run code
+2
source

You need to group the map first and then create the desired result

var output = {};
obj.forEach(function(val){
 output[val.key] = output[val.key] || [];
 output[val.key] = output[val.key].concat(val.value);
});

Now produce a concise output

var finalOutput = Object.keys(output).map(function(val){
      return { key: val, value: output[val] };
});

DEMO

var obj = [{
  key: 'black',
  value: ['2', '3', '9']
}, {
  key: 'black',
  value: ['1']
}, {
  key: 'gold',
  value: ['2', '3']
}, {
  key: 'gold',
  value: ['1']
}, {
  key: 'red',
  value: ['9']
}, {
  key: 'white',
  value: ['2', '3']
}, {
  key: 'white',
  value: ['1']
}];

var output = {};
obj.forEach(function(val) {
  var key = val.key;
  var value = val.value;
  output[key] = output[key] || [];
  output[key] = output[key].concat(val.value);
});

var finalOutput = Object.keys(output).map(function(val) {
  return {
    key: val,
    value: output[val]
  };
});

document.body.innerHTML += JSON.stringify(finalOutput,0,4);
Run code
0
source

- :

var input = ...
var reduced = [];
var reducedMap = {};

input.forEach(function(obj) {
  if(!reduced.hasOwnProperty(obj.key) {
    reduced[obj.key] = [];
  }

  for(var i = 0; i < obj.value.length; i++) {
    if(reduced[obj.key].indexOf(obj.value[i]) < 0) {
      reduced[obj.key].push(obj.value[i]);
    }
  }
});

reduced = Object.keys(reducedMap).map(function(key){
  return {
    key: key,
    value: reducedMap[key].sort()
  };
});
0

groupBy, map reduce :

  var result = 
      _(input)
          .groupBy('key')
          .map(function(d, key) {
              return {
                  key: key, 
                  value: _.reduce(d, function(a, dd) {
                      return a.concat(dd.value);
                  }, []).sort(),
              };
          })
          .value();

Try it here: https://jsfiddle.net/dw1zzfqt/1/

ES2015 Version

var result = 
    _(input)
        .groupBy('key')
        .map((d, key) => ({
            key, 
            value: _.reduce(d, (a, dd) => a.concat(dd.value), []).sort()
        }))
        .value();

Try it here: https://jsfiddle.net/dw1zzfqt/2/

0
source

All Articles