简体   繁体   English

在JavaScript中使用合并数组进行深度合并

[英]deep merge with concatenating arrays in javascript

I want to deep merge 2 javascript objects with similar properties in a reducer. 我想在reducer中深度合并具有类似属性的2个javascript对象。 The catch is the two objects have arrays as their properties and I need them to be concatenated instead of replaced. 要注意的是,这两个对象具有数组作为其属性,我需要将它们串联起来而不是替换。 Basically something like this: 基本上是这样的:

var x = {
  name: 'abc',
  family: {
    children: [
      {name: 'xxx'},
      {name: 'zzz'}
    ]
  }
};

var y = {
  name: 'abc',
  family: {
    children: [
      {name: 'yyy'}
    ]
  }
};

will result on 将导致

var y = {
  name: 'abc',
    family: {
      children: [
        {name: 'xxx'}, {name: 'zzz'}, {name: 'yyy'}
      ]
    }
  };

any suggestion? 有什么建议吗? I prefer lodash based solution if possible. 如果可能,我更喜欢基于lodash的解决方案。 Also, since it's in reducer, I cannot just replace the property with new object 另外,由于它在reducer中,所以我不能只用新对象替换该属性

objects have arrays as their properties and I need them to be concatenated instead of replaced 对象具有数组作为其属性,我需要将它们连接起来而不是替换掉

For your simple example it would be enough to use Array.prototype.concat() function: 对于您的简单示例,使用Array.prototype.concat()函数就足够了:

 var x = {name: 'abc', family:{children:[{name: 'xxx'}, {name: 'zzz'} ] }}, y = {name: 'abc', family: {children: [{name: 'yyy'}]}}; y.family.children = y.family.children.concat(x.family.children); console.log(y); 

If you're already using lodash, check if mergeWith doesn't do what you want... (see this so answer for example). 如果您已经在使用lodash,请检查mergeWith是否没有执行您想要的操作(例如,请参见此答案 )。

Anyway here is a quick function that should do what you want. 无论如何,这里是一个快速功能,可以执行您想要的操作。 Be warned that it does very little in terms of checking, and only merges properties that are in the first object (since you said that your objects are similar). 请注意,它在检查方面做的很少,只会合并第一个对象中的属性(因为您说过的对象是相似的)。

Also it doesn't mutate the objects but instead creates a new one. 此外,它不会突变对象,而是创建一个新对象。

 function merge(a, b){ var ret = {}; for(prop in a){ //assume b doesn't have properties that a hasn't //only merge on similar types, else keep a var propA = a[prop], propB = b[prop]; console.log(prop, typeof propA) if( (typeof propA == typeof propB) && (typeof propA == "object")){ if(Array.isArray(propA)){ ret[prop] = propA.concat(propB); }else{ ret[prop] = merge(propA, propB); } }else{ ret[prop] = propA; } } return ret; } var x = { name: 'abc', family: { children: [ {name: 'xxx'}, {name: 'zzz'} ] } }; var y = { name: 'abc', family: { children: [ {name: 'yyy'} ] } }; console.log(merge(x, y)); console.log(merge(y, x)); 

I assume one of your objects is the state you want to change in your reducer. 我假设您的对象之一是您要在减速器中更改的状态。

What about: 关于什么:

return Object.assign({}, x, {
   family: [...x.family, ...y.family]
  })

First this creates a new empty object and assigns x ( your old state ) to it. 首先,这将创建一个新的空对象,并为其分配x(您的旧状态)。 Afterwards it assigns the family which it overrides in the new object. 之后,它在新对象中分配被覆盖的族。 The ... represents all elements in an array, so this can be used to concat the arrays. ...表示数组中的所有元素,因此可以用来连接数组。

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

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