简体   繁体   English

如何在一个对象(包括内部对象)中合并对象数组-JavaScript?

[英]How to merge array of objects in one object, including inner objects - JavaScript?

Suppose I have the following array of objects: 假设我有以下对象数组:

var list = [
  { a: 1, 
    b: { c: 'x', k: []}
  },
  { a: 1,
    b: {c: 'x', d: 8}
  }
];

I want them to be merged into one "generic" object, for this example, it would be: 我希望将它们合并到一个“通用”对象中,对于本示例,它将是:

{a: 1, b: {c: 'x', d:'8', k[]}}

As you can see, all nested objects are merged too. 如您所见,所有嵌套对象也被合并。 But I can't gain it. 但是我无法获得它。 If I use Object.assign it creates new nested objects if they are different, that is duplicates them: 如果我使用Object.assign,则它们将创建新的嵌套对象(如果它们不同),即重复它们:

var res = Object.assign({}, ...list);
// res: {
    a: 1, 
    b: {c: 'x', k: []},
    b: {c: 'x', d: 8}
}

You could try the following using the reduce method: 您可以使用reduce方法尝试以下操作:

 var list = [{ a: 1, b: { a: 4, k: 3 } }, { a: 1, s: 11, b: { ab: 4, d: 8 } }] var result = list.reduce(function(acc, item) { var obj = { ...item } Object.keys(obj).forEach(function(item) { if (acc[item]) { //if a property with the the key, 'item' already exists, then append to that Object.assign(acc[item], obj[item]); } else { // else add the key-value pair to the accumulator object. acc[item] = obj[item]; } }) return acc; }, {}) console.log(result); 

Deep merging is not simple to do yourself, That blog uses deep merge . 进行深度合并并不是一件容易的事,该博客使用深度合并

If you don't have webpack or nodejs you can use deepmerge like so: 如果没有webpack或nodejs,则可以使用deepmerge,如下所示:

 // see https://github.com/facebook/react/blob/b5ac963fb791d1298e7f396236383bc955f916c1/src/isomorphic/classic/element/ReactElement.js#L21-L25 var canUseSymbol = typeof Symbol === 'function' && Symbol.for var REACT_ELEMENT_TYPE = canUseSymbol ? Symbol.for('react.element') : 0xeac7 function isReactElement(value) { return value.$$typeof === REACT_ELEMENT_TYPE } function isNonNullObject(value) { return !!value && typeof value === 'object' } function isSpecial(value) { var stringValue = Object.prototype.toString.call(value) return stringValue === '[object RegExp]' || stringValue === '[object Date]' || isReactElement(value) } function defaultIsMergeableObject(value) { return isNonNullObject(value) && !isSpecial(value) } function emptyTarget(val) { return Array.isArray(val) ? [] : {} } function cloneUnlessOtherwiseSpecified(value, options) { return (options.clone !== false && options.isMergeableObject(value)) ? deepmerge(emptyTarget(value), value, options) : value } function defaultArrayMerge(target, source, options) { return target.concat(source).map(function(element) { return cloneUnlessOtherwiseSpecified(element, options) }) } function mergeObject(target, source, options) { var destination = {} if (options.isMergeableObject(target)) { Object.keys(target).forEach(function(key) { destination[key] = cloneUnlessOtherwiseSpecified(target[key], options) }) } Object.keys(source).forEach(function(key) { if (!options.isMergeableObject(source[key]) || !target[key]) { destination[key] = cloneUnlessOtherwiseSpecified(source[key], options) } else { destination[key] = deepmerge(target[key], source[key], options) } }) return destination } function deepmerge(target, source, options) { options = options || {} options.arrayMerge = options.arrayMerge || defaultArrayMerge options.isMergeableObject = options.isMergeableObject || defaultIsMergeableObject var sourceIsArray = Array.isArray(source) var targetIsArray = Array.isArray(target) var sourceAndTargetTypesMatch = sourceIsArray === targetIsArray if (!sourceAndTargetTypesMatch) { return cloneUnlessOtherwiseSpecified(source, options) } else if (sourceIsArray) { return options.arrayMerge(target, source, options) } else { return mergeObject(target, source, options) } } deepmerge.all = function deepmergeAll(array, options) { if (!Array.isArray(array)) { throw new Error('first argument should be an array') } return array.reduce(function(prev, next) { return deepmerge(prev, next, options) }, {}) } var list = [{ a: 1, b: { c: 'x', //merging 1,2 and 1,3 results in [1,2,1,3] you can change that in defaultArrayMerge k: [1,2] } }, { a: 1, b: { c: 'x', k: [1,3], d: 8 } }]; console.log( deepmerge.all(list) ) 

You can use the reduce method. 您可以使用reduce方法。 Remove the first element from the original list , that object will be the base method. 从原始列表中删除第一个元素,该对象将成为基本方法。

 var list = [{ a: 1, b: { c: 'x', k: [] } }, { a: 1, b: { c: 'x', d: 8 } } ]; // Remove the first element from the array. The first element will be // the base object // slice will return a new array without the first object // apply reduce on this list let _temp = list.slice(1); let x = _temp.reduce(function(acc,curr,currIndex){ for(let keys in curr){ // checking if the base object have the same key as of current object if(acc.hasOwnProperty(keys)){ // if base object and current object has the key then // check if the type is an object if(typeof curr[keys] ==='object'){ // now get the key from both the object // & check which one is missong. Add that key and value to the // base object let keysFromACC = Object.keys(acc[keys]); let keysFromCURR = Object.keys(curr[keys]); keysFromCURR.forEach(function(item){ if(keysFromACC.indexOf(item) ===-1){ acc[keys][item] = curr[keys][item] } }) } } else{ // if the base object does not have key which current object // has then add the key to base object acc[keys]= curr[keys] } } return acc; },list[0]); console.log(x) 

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

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