javascript - JavaScript:使用 lodash 在相同的嵌套键之间进行过滤
问题描述
我有一个数组baseTable
,它看起来像这样:
baseTable = [
{
exid: "2",
name: "aa",
children_meta: {
has: false
}
},
{
exid: "1",
name: "aa1",
children_meta: {
has: false
}
},
{
exid: "3",
name: "bb",
children_meta: {
has: true
},
children: [
{
exid: "101",
name: "c101"
},
{
exid: "102",
name: "c102"
}
]
}
]
和另一个这样的数组againstTable
:
againstTable = [
{
exid: "2",
name: "aa",
children_meta: {
has: false
}
},
{
exid: "3",
name: "bb",
children_meta: {
has: true
},
children: [
{
exid: "102",
name: "c102"
}
]
}
]
是否有一种 lodash 方法可以从baseTable
数组中选择exid
不存在相同对象的对象againstTable
?
为了说明,我需要可以从上面的两个数组中产生以下数组结果的方法:
[
{
exid: "1",
name: "aa1",
children_meta: {
has: false
}
},
{
exid: "3",
name: "bb",
children_meta: {
has: true
},
children: [
{
exid: "101",
name: "c101"
}
]
}
]
这就是我尝试的方式,但这种方法对于一项小任务来说太大了:
conditionalRender(o: { baseTable; againstTable }) {
const { baseTable, againstTable } = o;
// Check if there are no duplicates in the base
// table; check against, "against table"
// This could be possible after user performs a search
console.log(baseTable, "..base");
console.log(againstTable, "...againsr");
const baseMap = {};
const againstMap = {};
baseTable.forEach(row => (baseMap[row.pid] = row));
againstTable.forEach(row => (againstMap[row.pid] = row));
// const against_ids = new Set(againstTable.map(({ pid }) => pid));
// return baseTable.filter(({ pid }) => !against_ids.has(pid));
const filteredBaseTable: { [index: string]: any } = [];
baseTable.forEach(({ pid }) => {
if (baseMap[pid].children_meta.has) {
// If it is a group, check if there exists
// a part in another table
if (againstMap[pid]) {
// Opposite table also has the same eequipment group
// Will keep the children that are not present in the
// opposite table
// Each child can be differentiated by its exid
const exidsInAgainstTable = new Set(
againstMap[pid].children.map(crow => crow.exid)
);
// Keep only those ids in base table that do not exist in against table
const originalBaseChildren = baseMap[pid].children;
baseMap[pid].children = originalBaseChildren.filter(
({ exid }) => !exidsInAgainstTable.has(exid)
);
filteredBaseTable.push(baseMap[pid]);
}
} else {
if (!againstMap[pid]) {
filteredBaseTable.push(baseMap[pid]);
}
}
});
return filteredBaseTable;
}
解决方案
这可以在不lodash
使用内置数组缩减的情况下实现。
例如,您可以调用数组 where 对于每次迭代,您都在其中搜索reduce
匹配on的项目。baseTable
againstTable
exid
如果未找到匹配项,请将 添加baseItem
到输出数组(这表示将上述数据中的exid:"2"添加到结果中的情况)。
如果找到匹配项,则检查baseItem
和againstItem
(如果存在)的子数组,并过滤baseItem.children
数组中该子数组exid
从未出现在againstItem.children
子数组中的项。如果过滤后的结果不为空,则baseItem
使用过滤后的结果更新 children 数组并将其添加到您的output
.
表达这一点的一种方法是代码:
const baseTable=[{exid:"2",name:"aa",children_meta:{has:false}},{exid:"1",name:"aa1",children_meta:{has:false}},{exid:"3",name:"bb",children_meta:{has:true},children:[{exid:"101",name:"c101"},{exid:"102",name:"c102"}]}];const againstTable=[{exid:"2",name:"aa",children_meta:{has:false}},{exid:"3",name:"bb",children_meta:{has:true},children:[{exid:"102",name:"c102"}]}];
const result = baseTable.reduce((output, baseItem) => {
const matchOnExid = againstTable.find(againstItem => {
return againstItem.exid === baseItem.exid;
});
if (matchOnExid) {
/* If match of exid found from agaistTable for current baseTable item
then examine the children sub-arrays */
const baseChildren = baseItem.children;
const againstChildren = matchOnExid.children;
if (Array.isArray(baseChildren) && Array.isArray(againstChildren)) {
/* If valid children sub-arrays exist of items, filter a subset of the
baseItem children for items that do not exist in the children sub-array
of the matched againstItem */
const matchChildrenOnExid = baseChildren.filter(baseChildItem =>
{
return againstChildren.every(againstChildItem => {
return againstChildItem.exid !== baseChildItem.exid;
});
});
if (matchChildrenOnExid.length > 0) {
/* If a subset of children do exist, then baseItem can be added to
resulting array. Note also that we need to update the children array
of the returned result to reflect the subset that was just found */
output.push({ ...baseItem,
children: matchChildrenOnExid
});
}
}
} else {
/* If no match of exid found, just add the baseItem to the
result */
output.push(baseItem);
}
return output;
}, []);
console.log(result);
推荐阅读
- html - 为什么我的 html 表单的密码输入字段有浅蓝色背景?
- ruby-on-rails - 来自 Rails API 调用的奇怪响应
- c# - 开发 azure 函数时有没有办法监视文件更改?
- algorithm - 回文链表问题 - 算法
- pandas - 熊猫:为什么没有附加数据框?
- dll - 尝试导入 sklearn 模块时 DLL 加载失败
- c - 如何用C编程语言在windows操作系统中编写一个类似于octave文档菜单界面的CLI菜单界面
- python - '++'在python中是什么意思?
- r - 如何估计组中的函数?
- java - 如果我们使用 Collections.synchrnizedList(Collection c),那么同步遍历块的目的是什么?