Merge javascript objects in array with same key

Using lodash

var array = [{name:"foo1",value:"val1"},{name:"foo1",value:["val2","val3"]},{name:"foo2",value:"val4"}];

function mergeNames (arr) {
    return _.chain(arr).groupBy('name').mapValues(function (v) {
        return _.chain(v).pluck('value').flattenDeep();
    }).value();
}

console.log(mergeNames(array));

2021 version

  • Using reduce to aggregate data.
  • Using logical nullish assignment only assigns if acc[name] is nullish (null or undefined).
  • Using Array.isArray to determines whether the passed value is an Array.

var arrays = [{ name: "foo1",value: "val1" }, {name: "foo1", value: ["val2", "val3"] }, {name: "foo2",value: "val4"}];

const result = arrays.reduce((acc, {name, value}) => {
  acc[name] ??= {name: name, value: []};
  if(Array.isArray(value)) // if it's array type then concat 
    acc[name].value = acc[name].value.concat(value);
  else
    acc[name].value.push(value);
  
  return acc;
}, {});

console.log(Object.values(result));

Here is another way of achieving that goal:

var array = [{
  name: "foo1",
  value: "val1"
}, {
  name: "foo1",
  value: [
    "val2",
    "val3"
  ]
}, {
  name: "foo2",
  value: "val4"
}];

var output = array.reduce(function(o, cur) {

  // Get the index of the key-value pair.
  var occurs = o.reduce(function(n, item, i) {
    return (item.name === cur.name) ? i : n;
  }, -1);

  // If the name is found,
  if (occurs >= 0) {

    // append the current value to its list of values.
    o[occurs].value = o[occurs].value.concat(cur.value);

    // Otherwise,
  } else {

    // add the current item to o (but make sure the value is an array).
    var obj = {
      name: cur.name,
      value: [cur.value]
    };
    o = o.concat([obj]);
  }

  return o;
}, []);

console.log(output);

Here is one option:-

var array = [{
  name: "foo1",
  value: "val1"
}, {
  name: "foo1",
  value: ["val2", "val3"]
}, {
  name: "foo2",
  value: "val4"
}];

var output = [];

array.forEach(function(item) {
  var existing = output.filter(function(v, i) {
    return v.name == item.name;
  });
  if (existing.length) {
    var existingIndex = output.indexOf(existing[0]);
    output[existingIndex].value = output[existingIndex].value.concat(item.value);
  } else {
    if (typeof item.value == 'string')
      item.value = [item.value];
    output.push(item);
  }
});

console.dir(output);