尝试使用过滤器设置具有唯一值的数组失败
Posted
技术标签:
【中文标题】尝试使用过滤器设置具有唯一值的数组失败【英文标题】:Trying to set an array with unique values using filter is failing 【发布时间】:2021-06-27 02:53:34 【问题描述】:我正在尝试合并 2 个数组,这些数组可能包含一些不同的键,从一个数组到另一个数组。
问题是它没有按应有的方式过滤已经合并的数组。我需要它具有独特的价值。
这是两个数组:
const arr1 = [
id: "1",
title: "My Name"
,
id: "2",
title: "Your Name"
,
group: [
id: "4",
title: "Some Agreement"
,
id: "5",
title: "Some Beer"
]
];
const arr2 = [
id: "1",
title: "Company Name",
,
id: "2",
title: "A title",
,
id: "3",
title: "Question Group 1",
,
id: "4",
title: "Confidentiality Agreement",
,
id: "5",
title: "Some more",
,
id: "6",
title: "Ayo",
];
第一个数组有时可能包含名为 group
的键,它是与核心数组 ( id: string, title: string )
中的对象具有相同类型的 2 个或更多项的混合。
第一个数组符合第二个数组中的项目。
现在我需要将 arr2
的所有项目发送到 arr1
而不从 arr2
中删除这些项目,但我需要从合并中排除现有的项目/ID,它们也必须针对group
键/数组中的项目进行测试。你明白了吗?
这应该是arr1
的最终结果:
const arr1 = [
id: "1",
title: "My Name"
,
id: "2",
title: "Your Name"
,
group: [
id: "4",
title: "Some Agreement"
,
id: "5",
title: "Some Beer"
]
,
id: "3",
title: "Question Group 1",
,
id: "6",
title: "Ayo",
]
如您所见,新项目必须添加到数组的末尾,该位置应保持不变。
我创建了一个可重现的示例:https://codesandbox.io/s/determined-beaver-r5t6v?file=/src/App.js
以及相关的代码:
const handleClick = () =>
setMerge((qs) =>
const merged = [...qs, ...qs2];
const unique = merged.filter((v, i, a) =>
return v.id === a[i].id;
);
return unique;
);
;
我到达那里是因为我什至无法根据数组的 id 通过唯一值过滤数组。
问题是这个功能可以开发不同的。我只需要不允许 arr2 中的重复项,包括 group
数组中的项。
【问题讨论】:
【参考方案1】:基本上,您似乎希望将第一个数组的所有内容复制到一个结果数组中,仅第二个数组中没有匹配的id
在第一个。
此解决方案利用对 group
属性数组的递归搜索,以及仅检查 id
属性的递归基本情况。
const isContained = (arr, element) => arr.some(el =>
if (el.group)
return isContained(el.group, element); // <-- recurse on group array
return el.id === element.id // <-- return ids match
);
...
const handleClick = () =>
setMerge((qs) =>
const merged = [
...qs, // <-- shallow copy first array
...qs2.filter((el) => !isContained(qs, el)), // <-- filtered second array
];
return merged;
);
;
【讨论】:
【参考方案2】:以下是实现所需输出的方法之一。
首先使用 arr1 中的ids
创建一个地图
过滤arr2
,其中在步骤1中创建的ids
映射中不存在的对象的ID
在步骤 2 中连接 arr1
和 filtered
数组
const arr1 = [id:"1",title:"My Name",id:"2",title:"Your Name",group:[id:"4",title:"Some Agreement",id:"5",title:"Some Beer"]];
const arr2 = [id:"1",title:"Company Name",id:"2",title:"A title",id:"3",title:"Question Group 1",id:"4",title:"Confidentiality Agreement",id:"5",title:"Some more",id:"6",title:"Ayo"];
//Create a Map with ids which are present in arr1
const ids = arr1.reduce((res, obj) =>
if(obj.group)
obj.group.forEach(innerObj =>
res[innerObj.id] = innerObj
);
else
res[obj.id] = obj;
return res;
, );
//console.log(ids);
//Filter out the arr2 where the id of an object is not
//present in the Map created above(i.e., ids object)
const filteredItems = arr2.filter((id) => !ids[id]);
//console.log(filteredItems);
//Concatenate arr1 and the filteredItems to get the final output
const finalRes = [...arr1, ...filteredItems];
console.log(finalRes);
.as-console-wrapper
max-height: 100% !important;
【讨论】:
【参考方案3】:您可以创建一个Set
来跟踪来自arr1
的现有ID,并且只添加来自arr2
且在arr1
中不存在的项目。
setMerge((qs) =>
const ids = new Set()
qs.forEach((item) =>
if (item.group)
item.group.forEach((el) => ids.add(el.id))
return
ids.add(item.id)
)
const itemsToAdd = qs2.filter((item) => !ids.has(item.id))
return [...qs, ...itemsToAdd]
)
【讨论】:
以上是关于尝试使用过滤器设置具有唯一值的数组失败的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Mongoose 查询过滤到数组类型字段中具有指定值的文档?