2755. 深度合并两个对象 🔒
2755. 深度合并两个对象 🔒
题目
Given two values obj1
and obj2
, return a deepmerged value.
Values should be deepmerged according to these rules:
- If the two values are objects, the resulting object should have all the keys that exist on either object. If a key belongs to both objects, deepmerge the two associated values. Otherwise, add the key-value pair to the resulting object.
- If the two values are arrays, the resulting array should be the same length as the longer array. Apply the same logic as you would with objects, but treat the indices as keys.
- Otherwise the resulting value is
obj2
.
You can assume obj1
and obj2
are the output of JSON.parse()
.
Example 1:
Input: obj1 = {"a": 1, "c": 3}, obj2 =
Output:
Explanation: The value of obj1["a"] changed to 2 because if both objects have the same key and their value is not an array or object then we change the obj1 value to the obj2 value. Key "b" with value was added to obj1 as it doesn't exist in obj1.
Example 2:
Input: obj1 = [{}, 2, 3], obj2 = [[], 5]
Output: [[], 5, 3]
Explanation: result[0] = obj2[0] because obj1[0] and obj2[0] have different types. result[2] = obj1[2] because obj2[2] does not exist.
Example 3:
Input:
obj1 = {"a": 1, "b": {"c": [1 , [2, 7], 5], "d": 2}},
obj2 = {"a": 1, "b": {"c": [6, [6], [9]], "e": 3}}
Output: {"a": 1, "b": {"c": [6, [6, 7], [9]], "d": 2, "e": 3}}
Explanation:
Arrays obj1["b"]["c"] and obj2["b"]["c"] have been merged in way that obj2 values overwrite obj1 values deeply only if they are not arrays or objects.
obj2["b"]["c"] has key "e" that obj1 doesn't have so it's added to obj1.
Example 4:
Input: obj1 = true, obj2 = null
Output: null
Constraints:
obj1
andobj2
are valid JSON values1 <= JSON.stringify(obj1).length <= 5 * 10^5
1 <= JSON.stringify(obj2).length <= 5 * 10^5
题目大意
给定两个值 obj1
和 obj2
,返回一个 深度合并 的值。
你应该遵循以下规则进行值的 深度合并 :
- 如果两个值都是对象,则结果对象应包含两个对象上存在的所有键。
- 如果一个键同时存在于两个对象中,则 深度合并 两个关联的值。否则,将键值对添加到结果对象中。
- 如果两个值都是数组,则结果数组的长度应与较长的数组相同。对于对象的合并逻辑,将索引视为键。
- 否则,结果值为
obj2
。
你可以假设 obj1
和 obj2
是 JSON.parse()
的输出结果。
示例 1:
输入: obj1 = {"a": 1, "c": 3}, obj2 =
输出:
**解释:**obj1["a"] 的值变为 2,因为如果两个对象具有相同的键且它们的值不是数组或对象,则将 obj1 的值更改为 obj2 的值。键 "b" 和其值被添加到 obj1 中,因为它在 obj1 中不存在。
示例 2:
输入: obj1 = [{}, 2, 3], obj2 = [[], 5]
输出:[[], 5, 3]
**解释:**result[0] = obj2[0],因为 obj1[0] 和 obj2[0] 类型不同。result[2] = obj1[2],因为 obj2[2] 不存在。
示例 3:
输入:
obj1 = {"a": 1, "b": {"c": [1 , [2, 7], 5], "d": 2}},
obj2 = {"a": 1, "b": {"c": [6, [6], [9]], "e": 3}}
输出:{"a": 1, "b": {"c": [6, [6, 7], [9]], "d": 2, "e": 3}}
解释:
数组 obj1["b"]["c"] 和 obj2["b"]["c"] 已合并,如果 obj2 的值不是数组或对象,则深度覆盖 obj1 的值。 obj2["b"]["c"] 有键 "e",而 obj1 中没有,所以将其添加到 obj1 中。
示例 4:
输入: obj1 = true, obj2 = null
输出: null
解释:
obj1
和obj2
都是有效的 JSON 值1 <= JSON.stringify(obj1).length <= 5 * 10^5
1 <= JSON.stringify(obj2).length <= 5 * 10^5
解题思路
类型判断:
- 题目要求如果两个值类型不同,则以
obj2
为准; - 首先判断
obj1
和obj2
是否都是对象,若其中一个不是对象,则直接返回obj2
, - 再判断它们是否为数组,如果一个是对象,另一个是数组,则直接返回
obj2
;
- 题目要求如果两个值类型不同,则以
处理数组:
- 如果
obj1
和obj2
都是数组,首先会创建一个新的数组,并将obj1
的所有值复制到新数组中。 - 然后,遍历
obj2
的索引,检查obj1
是否有相应的索引。如果有,递归合并这两个索引的值;如果没有,直接将obj2
中的索引值赋给新数组。
- 如果
处理对象:
- 如果
obj1
和obj2
都是对象,首先会创建一个新的对象,并将obj1
的所有键值对复制到新对象中。 - 然后,遍历
obj2
的键,检查obj1
是否有相应的键。如果有,递归合并这两个键的值;如果没有,直接将obj2
中的值赋给新对象。
- 如果
返回结果:
- 最终,返回合并后的对象或数组。
复杂度分析
- 时间复杂度:
O(n)
,其中n
是两个对象或数组中元素的总数,每个元素都需要被递归访问一次。 - 空间复杂度:
O(n)
,其中n
是递归深度或元素总数,递归合并时需要额外的栈空间。
代码
/**
* @param {Object|Array} obj1
* @param {Object|Array} obj2
* @return {Object}
*/
var deepMerge = function (obj1, obj2) {
const isObject = (obj) => typeof obj === 'object' && obj !== null;
const isArray = (obj) => Array.isArray(obj);
// 如果 obj1 或 obj2 是基本类型,直接返回 obj2
if (!isObject(obj1) || !isObject(obj2)) return obj2;
// 如果 obj1 和 obj2 类型不一致(一个是对象,一个是数组),直接返回 obj2
if (isArray(obj1) !== isArray(obj2)) return obj2;
// 如果两个都是数组,则合并数组元素
if (isArray(obj1) && isArray(obj2)) {
const result = [...obj1];
for (let i = 0; i < maxLength; i++) {
result[i] = deepMerge(obj1[i], obj2[i]);
}
return result;
}
// 如果是对象,则递归合并每个键值对
const result = { ...obj1 }; // 创建一个新的对象避免修改原始对象
for (let key in obj2) {
result[key] = deepMerge(obj1[key], obj2[key]);
}
return result;
};