简体   繁体   English

使用相同的键合并数组中的 JavaScript 对象

[英]Merge JavaScript objects in array with same key

What is the best way to merge array contents from JavaScript objects sharing a key in common?从共享一个共同键的 JavaScript 对象中合并数组内容的最佳方法是什么?

How can array in the example below be reorganized into output ?下面示例中的array如何重组为output Here, all value keys ( whether an array or not ) are merged into all objects sharing the same name key.在这里,所有value键(无论是否为数组)都被合并到共享相同name键的所有对象中。

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"
        ]
    }
];

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

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

Using lodash使用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));

Here is a version using an ES6 Map:这是一个使用 ES6 Map 的版本:

 const arrays = [{ name: "foo1",value: "val1" }, {name: "foo1", value: ["val2", "val3"] }, {name: "foo2",value: "val4"}]; const map = new Map(arrays.map(({name, value}) => [name, { name, value: [] }])); for (let {name, value} of arrays) map.get(name).value.push(...[value].flat()); console.log([...map.values()]);

Try this:尝试这个:

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

2021 version 2021版

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

Using reduce:使用减少:

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]) 
}
const exampleObj = [{
  year: 2016,
  abd: 123
}, {
  year: 2016,
  abdc: 123
}, {
  year: 2017,
  abdcxc: 123
}, {
  year: 2017,
  abdcxcx: 123
}];
const listOfYears = [];
const finalObj = [];
exampleObj.map(sample => {    
  listOfYears.push(sample.year);
});
const uniqueList = [...new Set(listOfYears)];
uniqueList.map(list => {   
  finalObj.push({
    year: list
  });
});
exampleObj.map(sample => {    
  const sampleYear = sample.year;  
  finalObj.map((obj, index) => {     
    if (obj.year === sampleYear) {        
      finalObj[index] = Object.assign(sample, obj);       
    }  
  }); 
});

The final object be [{"year":2016,"abdc":123,"abd":123},{"year":2017,"abdcxcx":123,"abdcxc":123}]最终对象是 [{"year":2016,"abdc":123,"abd":123},{"year":2017,"abdcxcx":123,"abdcxc":123}]

This work too !这工作太!

 var array = [ { name: "foo1", value: "val1", }, { name: "foo1", value: ["val2", "val3"], }, { name: "foo2", value: "val4", }, ]; let arr2 = []; array.forEach((element) => { // remove duplicate name let match = arr2.find((r) => r.name == element.name); if (match) { } else { arr2.push({ name: element.name, value: [] }); } }); arr2.map((item) => { array.map((e) => { if (e.name == item.name) { if (typeof e.value == "object") { //lets map if value is an object e.value.map((z) => { item.value.push(z); }); } else { item.value.push(e.value); } } }); }); console.log(arr2);

try this :尝试这个 :

 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" ] } ]; bb = Object.assign( {}, array, output ); console.log(bb) ;

It's been a while since this question was asked, but I thought I'd chime in as well.自从问这个问题已经有一段时间了,但我想我也会插话。 For functions like this that execute a basic function you'll want to use over and over, I prefer to avoid longer-written functions and loops if I can help it and develop the function as a one-liner using shallow Array.prototype functions like .map() and some other ES6+ goodies like Object.entries() and Object.fromEntries() .对于像这样执行基本函数的函数,你会想要一遍又一遍地使用,如果我可以帮助它并使用浅层 Array.prototype 函数将函数开发为单行函数,我更愿意避免编写较长的函数和循环.map()和其他一些 ES6+ 好东西,比如Object.entries()Object.fromEntries() Combining all these, we can execute a function like this relatively easily.结合所有这些,我们可以相对轻松地执行这样的函数。

First, I take in however many objects you pass to the function as a rest parameter and prepend that with an empty object we'll use to collect all the keys and values.首先,我接受你传递给函数的许多对象作为一个 rest 参数,并在它前面加上一个空对象,我们将用它来收集所有的键和值。

[{}, ...objs]

Next, I use the .map() Array prototype function paired with Object.entries() to loop through all the entries of each object, and any sub-array elements each contains and then either set the empty object's key to that value if it has not yet been declared, or I push the new values to the object key if it has been declared.接下来,我使用与Object.entries()配对的.map()数组原型函数来循环遍历每个对象的所有条目,以及每个包含的任何子数组元素,然后将空对象的键设置为该值,如果它尚未声明,或者我将新值推送到对象键(如果已声明)。

[{},...objs].map((e,i,a) => i ? Object.entries(e).map(f => (a[0][f[0]] ? a[0][f[0]].push(...([f[1]].flat())) : (a[0][f[0]] = [f[1]].flat()))) : e)[0]

Finally, to replace any single-element-arrays with their contained value, I run another .map() function on the result array using both Object.entries() and Object.fromEntries() , similar to how we did before.最后,为了用它们包含的值替换任何单元素数组,我使用Object.entries()Object.fromEntries()在结果数组上运行另一个.map()函数,类似于我们之前所做的。

let getMergedObjs = (...objs) => Object.fromEntries(Object.entries([{},...objs].map((e,i,a) => i ? Object.entries(e).map(f => (a[0][f[0]] ? a[0][f[0]].push(...([f[1]].flat())) : (a[0][f[0]] = [f[1]].flat()))) : e)[0]).map(e => e.map((f,i) => i ? (f.length > 1 ? f : f[0]) : f)));

This will leave you with the final merged object, exactly as you prescribed it.这将为您留下最终合并的对象,完全按照您的规定。

 let a = { a: [1,9], b: 1, c: 1 } let b = { a: 2, b: 2 } let c = { b: 3, c: 3, d: 5 } let getMergedObjs = (...objs) => Object.fromEntries(Object.entries([{},...objs].map((e,i,a) => i ? Object.entries(e).map(f => (a[0][f[0]] ? a[0][f[0]].push(...([f[1]].flat())) : (a[0][f[0]] = [f[1]].flat()))) : e)[0]).map(e => e.map((f,i) => i ? (f.length > 1 ? f : f[0]) : f))); getMergedObjs(a,b,c); // { a: [ 1, 9, 2 ], b: [ 1, 2, 3 ], c: [ 1, 3 ], d: 5 }

Use lodash "uniqWith".使用 lodash “uniqWith”。 As shown below如下所示

let _ = require("lodash");

var array = [
  { name: "foo1", value: "1" },
  { name: "foo1", value: "2" },
  { name: "foo2", value: "3" },
  { name: "foo1", value: "4" }
];

let merged = _.uniqWith(array, (pre, cur) => {
  if (pre.name == cur.name) {
    cur.value = cur.value + "," + pre.value;
    return true;
  }
  return false;
});

console.log(merged);
// output:  [{ name: "foo1", value: "1,2,4" }, { name: "foo2", value: "3" }];


 const array = [{ name: "foo1", value: "val1" }, {name: "foo1", value: ["val2", "val3"] }, {name: "foo2", value: "val4"}]; const start = array.reduce((object, {name}) => ({...object, [name]: []}), {}); const result = array.reduce((object, {name, value}) => ({...object, [name]: [object[name], [value]].flat(2)}), start); const output = Object.entries(result).map(([name, value]) => ({name: name, value: value})); console.log(output);

A much more easier approach is this 2022:更简单的方法是 2022 年:

  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"
            ]
        }
    ];
    
    function mergeBasedOnKey(list){
      let c = Object.values(list.reduce((a, b) => {
    
        a[b.name] = a[b.name] || {name: b.name, value: []}
        if(typeof(b['value']) == "string"){
          a[b.name].value.push(b['value'])
        }
        else{
          a[b.name].value = [...a[b.name].value, ...b.value]
        }
    
        return a
    
      }, {}))
      return c
    }
   let ans = mergeBasedOnKey(array)
   console.log(ans)

I was looking for a quick, almost "one-liner" answer in this thread, provided that this is a trivial but common exercise.我在这个线程中寻找一个快速的、几乎“单行”的答案,前提是这是一个微不足道但常见的练习。

I couldn't find any for my like.我找不到任何我喜欢的。 The other answers are fine but I am not much into boilerplate.其他答案很好,但我不太喜欢样板。

So, let me add one, then:那么,让我添加一个,然后:

o=array.reduce((m,{name:n,value:v})=>({...m,[n]:[...(m[n]||[]),v].flat(2)}),{})
output=Object.entries(o).map(([n,v])=>({name:n,value:v}))

 var array = [ { name: "foo1", value: "val1"}, { name: "foo1", value: ["val2","val3"] }, { name: "foo2", value: "val4" } ] obj= array.reduce((o,{name:n,value:v})=>({...o,[n]:[...(o[n]||[]),v].flat(2)}),{}) output= Object.entries(obj).map(([n,v])=>({name:n,value:v})) console.log(output)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM