[英]how to rescursively deep merge an array of objects
I want to merge two arrays of objects. 我想合并两个对象数组。 Those objects have the same structure, but one of them is missing the hide property.
这些对象具有相同的结构,但是其中之一缺少hide属性。 I want to copy the value of hide property from one object to the other that is missing this property.
我想将hide属性的值从一个对象复制到另一个缺少此属性的对象。 The important part is that I don't want to mutate any of these arrays!
重要的是,我不想突变任何这些阵列!
The first array looks like this (notice that there is hide property): 第一个数组如下所示(注意,这里有hide属性):
let first_array = [
{
name: 'John',
age: 40,
hide: true,
childs: [
{
name: 'Alice',
age: 20,
hide: false,
childs: [
{
name: 'Mike',
age: 2,
hide: true
}
]
}
]
},
{
name: 'Peter',
age: 40,
hide: true,
childs: [
{
name: 'Andrew',
age: 20,
hide: true,
childs: [
{
name: 'Jessica',
age: 2,
hide: true
}
]
}
]
}
]
The second array looks almost the same! 第二个数组看起来几乎一样! The only thing missing is hide property.
唯一缺少的是hide属性。
let second_array = [
{
name: 'John',
age: 40,
childs: [
{
name: 'Alice',
age: 20,
childs: [
{
name: 'Mike',
age: 2,
}
]
}
]
},
{
name: 'Peter',
age: 40,
childs: [
{
name: 'Andrew',
age: 20,
childs: [
{
name: 'Jessica',
age: 2,
}
]
}
]
}
]
Now, I want to create new array with where within each object there is hide property. 现在,我想创建一个新数组,其中每个对象中都有hide属性。
I know how to do this recursively in the imperative
way, but unfortunately I'm mutating data - which I don't want to do. 我知道如何以
imperative
方式递归执行此操作,但是不幸的是,我正在对数据进行变异-我不想这样做。
function getHideProperty(first, second) {
for (let i = 0; i < second.length; i++) {
for (let j = 0; j < first.length; j++) {
if (second[i].name === first[j].name) {
second[i].hide = first[j].hide
if (second[i].childs) {
second[i].childs = getHideProperty(first[j].childs, second[i].childs)
}
}
}
}
return second
}
Now I can create new array with merged objects: 现在,我可以创建带有合并对象的新数组:
const newArray = getHideProperty(second_array, first_array)
Now, every object in second_array has hide property. 现在,second_array中的每个对象都具有hide属性。 But I mutated the array :(
但是我改变了数组:(
How to achieve such result without mutating the array? 如何在不更改数组的情况下实现这种结果?
You'll need to: 您需要:
Create a new array to store the new information, and return that 创建一个新数组来存储新信息,并返回
Deep-copy second[i]
to store in the new array, prior to modifying anything 在修改任何内容之前,对
second[i]
进行深拷贝以存储在新阵列中
For #2, choose your favorite answer from What is the most efficient way to deep clone an object in JavaScript? 对于#2,请从“在JavaScript中深度克隆对象的最有效方法是什么”中选择最喜欢的答案?
For #1, very roughly (see comments): 对于#1,非常粗略(请参阅评论):
function getHideProperty(first, second) {
const result = []; // Our result array
for (let i = 0; i < second.length; i++) {
const secondEntry = result[i] = deepCopy(second[i]); // The deep copy, and let's avoid constantly re-retrieving second[i]/result[i]
for (let j = 0; j < first.length; j++) {
if (secondentry.name === first[j].name) {
secondentry.hide = first[j].hide
if (secondEntry.childs) {
// Could be more efficient here, since the entries in `childs` are already copies; left as an exercise to the reader...
secondEntry.childs = getHideProperty(first[j].childs, secondEntry.childs)
}
}
}
}
return result;
}
This is not meant to be an all-singing, all-dancing solution. 这并不是一个全力以赴的解决方案。 It's meant to help you along the way.
它旨在为您提供全程帮助。 Note the
deepCopy
placeholder for your preferred solution to #2. 注意您对#2的首选解决方案的
deepCopy
占位符。 :-) :-)
If you do something like the above (nested loops) and find that it's a performance problem, you can create a Map
of the entries in first
keyed by their names, and then look them up in the map when looping through second
(rather than the nested loop). 如果你这样做上述(嵌套循环),并发现它的性能问题,您可以创建一个
Map
中的条目的first
由他们的名字键,然后看看他们在地图上通过循环时, second
(而不是嵌套循环)。 The complexity is only useful if you run into a performance problem with the simple nested loops solution. 仅当您使用简单的嵌套循环解决方案遇到性能问题时,复杂性才有用。
This is a functional approach that doesn't mutate any of the original arrays or their items: 这是一种不改变任何原始数组或其项目的功能方法:
function getHideProperty(first, second) {
return second.map(function(item) {
var corresponding = first.find(function(searchItem) {
return searchItem.name === item.name;
});
return Object.assign({},
item,
{ hide: corresponding.hide },
item.childs
? { childs: getHideProperty(item.childs, corresponding.childs) }
: {}
);
});
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.