web-dev-qa-db-fra.com

Fusionner des objets javascript dans un tableau avec la même clé

Quel est le meilleur moyen de réorganiser array en output? J'ai besoin de fusionner toutes les clés de valeur (que ce soit un tableau ou non) dans des objets partageant la même clé de nom. Il y a quelque chose de similaire ici , mais cela ne répond pas à ma question car j'ai aussi des tableaux.

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

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

Oui, je peux écrire sans fin des boucles for et plusieurs tableaux, mais existe-t-il un simple raccourci (r)? Merci!

20
Wagtail

Voici une 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);

21
BenG

Voici un autre moyen d'atteindre cet objectif:

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;
}, []);
7
Hunan Rostomyan

Utiliser 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));
3
paolobueno

Essaye ça:

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

for(var j=0;j<array.length;j++){
  var current = array[j];
  for(var i=j+1;i<array.length;i++){
    if(current.name = array[i].name){
      if(!isArray(current.value))
        current.value = [ current.value ];
      if(isArray(array[i].value))
         for(var v=0;v<array[i].value.length;v++)
           current.value.Push(array[i].value[v]);
      else
        current.value.Push(array[i].value);
      array.splice(i,1);
      i++;
    }
  }
}

function isArray(myArray) {
    return myArray.constructor.toString().indexOf("Array") > -1;
}

document.write(JSON.stringify(array));

1
Racil Hilan

Utilisation de réduire:

var mergedObj = array.reduce((acc, obj) => {
    if (acc[obj.name]) {
       acc[obj.name].value = acc[obj.name].value.isArray ? 
       acc[obj.name].value.concat(obj.value) : 
       [acc[obj.name].value].concat(obj.value);

    } else {
      acc[obj.name] = obj;
    }

    return acc;
}, {});

let output = [];
for (let prop in mergedObj) {
  output.Push(mergedObj[prop]) 
}
0
unamaga