我有兩個物件,其結構如下:
我有兩個物件,其結構如下:
let sourceObj=[
{
items: [
{ items: [{ id: '0'/span>, name: 'z' }], name: 'm' },
{ items: [{ id: '2', name: 'q' }], name: 'l' },
],
name: 'c'
},
{
items: [
{ items: [{ id: '4', name: '-' }], name: 'v' },
],
name: 'd'/span>
}
];
let targetObj = [
{
items: [
{ items: [{ id: '1', name: 'd' }], name: 'm' },
{ items: [{ id: '3', name: 'b' }], name: 'j' },
],
name: 'c'
}
];
我想合并這個物件,得到一個有下一個結構的物件:
我想合并這個物件,得到一個有下一個結構的物件。
let merged = [
{
items: [
{ items: [...
{ id: '0', name: 'd' },
{ id: '1', name: 'z' }]。
name: 'm'
},
{ items: [{ id: '2', name: 'q' }], name: 'l' },
{ items: [{ id: '3', name: 'b' }], name: 'j' },
],
name: 'c'
},
{
items: [
{ items: [{ id: '4', name: '-' }], name: 'v' },
],
name: 'd'/span>
}
也就是說,如果源陣列的名字在目標陣列中是相同的,我想獲得已加入陣列的物件。
我試著用lodash方法mergeWith,但我只能連接集合的上層項......
我試著用lodash方法mergeWith。
mergeWith(sourceObj, targetObj, (objValue, srcValue) => //span> {
if (isArray(objValue)) {
return objValue.concat(srcValue)。
}
});
uj5u.com熱心網友回復:
你是正確的,Lodash的mergeWith不會遞回地合并。你可以自己手動管理這個。
- 首先,我們將迭代一個新的資料。
- 首先迭代第一個陣列并通過
name屬性生成一個map物件。 - 然后遍歷第二個陣列,檢查
name屬性是否匹配。 匹配,如果是的話,遞回呼叫merge函式來合并 源陣列和目標陣列的兩個嵌套陣列,否則,將第二個陣列的元素添加到 第二個陣列的元素添加到物件映射中。 。
- 最后,將 地圖物件轉換為合并后的值的陣列。
代碼:
const merge = (sourceArr, targetArr)=> {
// (1) 生成查找地圖。
const objMap = sourceArr.reduce((map, curr) => {
return {
...地圖。
[curr.name]: curr
};
}, {});
// (2) 合并物件,對專案陣列進行遞回。
targetArr.forEach((obj) => {
if (objMap[obj.name] ) {
objMap[obj.name].items = merge(objMap[obj. name].items, obj.items)。)
} else {
objMap[obj.name] = obj;
}
});
// (3) 回傳合并值陣列 return Object.values(objMap)。
};
const sourceObj = [
{
items: [
{ items: [{ id: "0"/span>, name: "z" }], name: "m" },
{ items: [{ id: "2"/span>, name: "q" }], name: "l" }, name: "l" }
],
name: "c"/span>
},
{
items: [{ items: { id: "4"/span>, name: "-" }], name: "v" }]。
name: "d"
}
];
const targetObj = [
{
items: [
{ items: [{ id: "1"/span>, name: "d"/span> }], name: "m" },
{ items: [{ id: "3"/span>, name: "b" }], name: "j" }, name: "j" }
],
name: "c"
}
];
const merge = (sourceArr, targetArr) => {
const objMap = sourceArr.reduce((map, curr) => {
return {
...地圖。
[curr.name]: curr
};
}, {});
targetArr.forEach((obj) =>; {
if (objMap[obj.name] ) {
objMap[obj.name].items = merge(objMap[obj. name].items, obj.items)。)
} else {
objMap[obj.name] = obj;
}
});
return Object.values(objMap)。
};
const res = merge(sourceObj, targetObj);
console.log(res);
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" class="snippet-box-edit snippet-box-result" frameborder="0"></iframe>
CodePudding
我發現一劑相互遞回使得這里的代碼更加簡潔。
。const combineItems =(o = {}, items)=>
o .items || items .length ? {items: deepMerge (o.items || [], items)} : {}
const deepMerge = (xs, ys) =>
Object .values ([... xs, ... ys] .reduce (
(a, {name, items = [], ...rest}) => ({
... a,
[名稱]: {
... (a [name] || {name, ...rest})。
... combineItems (a [name], items)
}
}), {}
))
const sourceObj = [{items: [{items: [{id: "0"/span>, name: "z"}], name: "m"/span>}, {items: [{id: "2"/span>, name: "q"}], name: "l"}], name: "c"}, {items: [{items: [id: "4"/span>, name: "-"}], name: "v"}], name: "d"}]
const targetObj = [{items: [{items: [{id: "1"/span>, name: "d"}], name: "m"/span>}, {items: [{id: "3"/span>, name: "b"}], name: "j"}], name: "c"}]。
console .log (deepMerge (sourceObj, targetObj))/code>
.as-console-wrapper {max-height: 100% ! important; top: 0}
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" class="snippet-box-edit snippet-box-result" frameborder="0"></iframe>
deepMerge是主函式,但它委托給combineItems來處理我們是否已經有專案要合并的各種組合。 combineItems將回傳類似{items: [<item1>. <item2>, ...]}或者只是{},這取決于是否找到了任何專案。
這里存在一個潛在的性能問題,Rich Snapp 將其稱為減少({...傳播})反模式。 如果代碼的性能令你滿意,我個人不會在這里擔心它。 但如果不是這樣,我們可以根據他的建議進行修改,變成這樣:
const deepMerge = (xs, ys)=>
Object .values ([... xs, ... ys] .reduce (
(a, {name, items = [], ...rest}) => {
const x = a [name] || {name, ...rest}.
if (items.length || x.items)
x .items = deepMerge (x .items || [], items)
a [name] = x
return a
}, {}
))
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/326075.html
標籤:
