如何合并两个对象,覆盖空值?

4

我希望合并两个类似但不完全相同的对象,并在其中一个对象中覆盖空值(如果有)。例如,我有以下这两个对象:

const obj1 = {
    a: 1,
    b: '',
    c: [],
    d: null
}

const obj2 = {
    a: 2,
    b: null,
    d: 1
}

合并的效果应该是:
const objMerged = {
    a: 2,
    b: '',
    c: [],
    d: 1
}

换句话说,合并对象中数据的最重要来源是obj2,但它缺少一些来自obj1的属性,因此需要复制这些属性。 另外,obj2 的某些值为空,所以也应该从obj1 中获取这些值。
_.extend({}, obj1, obj2) 

并且

Object.assign({}, obj1, obj2)

1
在提问之前,你尝试过任何方法吗? - depperm
是的,Object.assign和lodash extend函数。 - Hubert Kubiak
1
你能在问题中包含你的尝试吗? - depperm
Object.assign({}, obj1, obj2); 将obj1和obj2的属性浅拷贝合并到一个空对象中。 - Hubert Kubiak
把以下与编程有关的内容从英语翻译成中文。只返回翻译后的文字:请编辑问题,附上两次尝试。 - depperm
首先,尝试移除“null”值如何? - Ngob
8个回答

14

您还可以混合使用ES6解构和lodash的_.omitBy

const obj1 = { a: 1, b: '', c: [], d: null }
const obj2 = { a: 2, b: null, d: 1 }

const result = {..._.omitBy(obj1, _.isNull), ..._.omitBy(obj2, _.isNull)}

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

你也可以仅使用ES6来完成它,例如这样:

const obj1 = { a: 1, b: '', c: [], d: null }
const obj2 = { a: 2, b: null, d: 1 }

let omitNull = obj => {
  Object.keys(obj).filter(k => obj[k] === null).forEach(k => delete(obj[k]))
  return obj
}

const result = { ...omitNull(obj1), ...omitNull(obj2) }

console.log(result)


5

您可以使用_.mergeWith()函数,在合并回调中仅在第二个值不为null时才取它:

const obj1 = { a: 1, b: '', c: [], d: null }
const obj2 = { a: 2, b: null, d: 1 }

const result = _.mergeWith({}, obj1, obj2, (o, s) => _.isNull(s) ? o : s)

console.log(result)
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.11/lodash.min.js"></script>


5
为了补充这些好答案,这里提供一个递归解决方案,可用于嵌套结构。
此示例将合并dst对象的共同属性到所有嵌套级别的src对象中,保留任何不共同的属性。

const merge = (dst, src) => {
  Object.keys(src).forEach((key) => {
    if (!dst[key]) {
      dst[key] = src[key];
    } else if (typeof src[key] === 'object' && src[key] !== null && typeof dst[key] === 'object' && dst[key] !== null) {
      merge(dst[key], src[key]);
    }
  });
},

/* Usage: */

src = {
  prop1: '1',
  prop2: {
    val: 2,
  }
},
dst = {
  prop1: null,
  prop2: {
    val: null,
  },
  prop3: null,
};

merge(dst, src);
console.log(dst);


2
很棒的答案。我非常喜欢这个解决方案! - 010011100101
很好,不过我建议使用if (dst[key] == null),因为即使整数为0,它也会被替换,尽管它不是null。 - Oleg Fridman

3

以下是基于纯JS的解决方案:

遍历第一个对象以替换第二个对象中的值,然后添加第二个对象中的附加值。

const obj1 = {
    a: 1,
    b: '',
    c: [],
    d: null
}

const obj2 = {
    a: 2,
    b: null,
    d: 1
}

function mergeObjs(obj1, obj2){
  const merged = {}
  keys1 = Object.keys(obj1);
  keys1.forEach(k1 => {
     merged[k1] = obj2[k1] || obj1[k1]; // replace values from 2nd object, if any
  })
  Object.keys(obj2).forEach(k2 => {
     if (!keys1.includes(k2)) merged[k2] = obj[k2]; // add additional properties from second object, if any
  })
  return merged
}


console.log(mergeObjs(obj1, obj2))


需要将 "merged[k2] = obj[k2]" 合并为 "merged[k2] = obj2[k2]"。 - Dave

2
使用 Lodash 的 create()omitBy()

const obj1 = {"a":1,"b":"","c":[],"d":null}

const obj2 = {"a":2,"b":null,"d":1}

const objMerged = _.create(
  _.omitBy(obj1, _.isNull),
  _.omitBy(obj2, _.isNull)
)

console.log(objMerged)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>


1
如果您只对这两个对象的第一级感兴趣,可以像这样操作:

const obj1 = {
  a: 1,
  b: '',
  c: [],
  d: null
}

const obj2 = {
  a: 2,
  b: null,
  d: 1
}

const merged = Object.keys(obj1).concat(Object.keys(obj2)) // create an array that contains the keys of the two objects.
  .filter((k, i, arr) => arr.indexOf(k) === i) // remove duplicate keys
  .reduce((a, c) => {
    a[c] = obj1[c] !== null ? obj1[c] : obj2[c];
    return a;
  }, {});

console.log(merged);

这个例子只检查null值,你应该扩展它来检查其他值,如undefined,空字符串等。

1
var objMerged  = {};
for (var kobj1 in obj1) {
    for (var kobj2 in obj2) {
        if (obj1[kobj1] == null && obj2[kobj1] != null)
            objMerged[kobj1] = obj2[kobj1];
        else if (obj2[kobj2] == null && obj1[kobj2] != null)
            objMerged[kobj2] = obj1[kobj2];

    }
}

//将objMerged打印以显示


1
你使用了Object.assign的好办法,只需在之前删除不需要的内容即可。
Object.keys(obj1).forEach( k => {
    if ( obj1[k] //write the condition you want
        delete obj1[k]
});

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