将具有相同键的JavaScript对象合并到数组中

70

如何在JavaScript对象中,将具有共同键的数组内容合并起来?

在下面的示例中,如何重新组织array以得到output?这里,所有共享相同name键的对象中的value键(无论是数组还是其他类型)都将被合并。

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

1
数组 array 是否会变成 {name:"foo1",value:["val1"]} - BenG
@BG101 不是数组,但如果这有帮助的话,我可以事先制作它。 - zdebruine
1
你尝试过使用jQuery的extend()方法吗?或者你正在尝试编写自己的合并脚本吗?那么可能会像这样:var newArray = $.extend({}, array, output); - user3186219
1
您是否有特定的内容合并方式,或者$.extend()就可以胜任? - user3186219
@ZachPerkitny 我不确定 $.extend() 是否足够,因为我必须处理键值内的数组。 - zdebruine
请给我一个示例,说明您希望如何合并它。 - user3186219
16个回答

2

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


2

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


2

我在这个帖子里寻找一个快速、几乎是“一行代码”的答案,因为这是一个简单但常见的练习。

但我没有找到符合我要求的答案。其他答案都不错,但我不太喜欢样板文件。

所以,让我来添加一个:

o = array.reduce((m,{name:n,value:v})=>({...m,[n]:[...m[n]||[],v].flat(1)}),{})
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" }
]

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


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

最终的对象是 [{"year":2016,"abdc":123,"abd":123},{"year":2017,"abdcxcx":123,"abdcxc":123}]。

1
一种更加简单的方法是使用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)

你真是个救命恩人!这种方法非常酷!我试过所有好的答案,但这个太棒了,谢谢! - DineshMsd

0
对于像我一样来到这里寻找类似问题解决方案的人...
我的情况有点不同...
这是我使用`_.mergeWith`的解决方案。
// pre grouped array with _.groupBy
const source = {
    obj1: [{label: null, count: null }, {label: null, count: 10 }, {label: 'value1', count: null }],
    obj2: [{label: 'value2', count: 5 }, {label: null, count: null }],
    obj3: [{label: null, count: null }, {label: null, count: null }, {label: null, count: 15 }, {label: 'value3', count: null }],
    obj4: [{label: null, count: null }, {label: null, count: null }, {label: null, count: null }, {label: null, count: null }],
}

function combineObjects(key, source) {
    // spread the source array so not to mutate the original source with `.shift()` when getting the first object to merge with
    return _.mergeWith([...source[key]].shift(), ...source[key], (objValue, srcValue) => {
        if (srcValue !== null) return srcValue
        return objValue
    })
}

const combinedObjects = Object.keys(source).map(key => combineObjects(key, source))

// combinedObjects -> [{label: 'value1', count: 10 },{label: 'value2', count: 5 },{label: 'value3', count: 15 }, {label: null, count: null}]


希望这能帮助到遇到类似情况的人。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接