如何防止数组中的重复项?
Posted
技术标签:
【中文标题】如何防止数组中的重复项?【英文标题】:How to prevent duplicate items in array? 【发布时间】:2020-01-24 19:47:00 【问题描述】:我有两个数组,我想将一些项目从 arr1 推送到 arr2 以防止重复,因为我已经向 arr2 添加了一些项目,这些项目也在 arr1 中。我在 react js 中这样做
arr1.forEach(q1 =>
arr2.forEach(q2 =>
if (q1.lessonId !== q2.lessonId)
if (q2.obtainedMarks >= q2.passingMarks)
User.findByIdAndUpdate(req.body.userId, $push: arr1: $each:
[q2._id] , (err, doc) =>
)
)
);
【问题讨论】:
【参考方案1】:您可以使用集合而不是数组。它们具有防止重复条目的内置功能。见https://developer.mozilla.org/en-US/docs/Web/javascript/Reference/Global_Objects/Set
【讨论】:
【参考方案2】:我不知道你的 User.findByIdAndUpdate
或 $push
做了什么,但如果你只是想在第一个数组中组合第二个数组中的非重复项,只有当标记比较有效时,你可以写一些东西像这样:
const addWithoutDups = (arr1, arr2, ids = new Set (arr1 .map (x => x .lessonId))) =>
[
...arr1,
...arr2.filter((x) => !ids .has (x .lessonId) && x .obtainedMarks > x .passingMarks)
]
const arr1 = [
lessonId: 1, more: 'here...',
lessonId: 2, more: 'here...',
lessonId: 3, more: 'here...',
lessonId: 4, more: 'here...'
]
const arr2 = [
lessonId: 2, obtainedMarks: 10, passingMarks: 7,
lessonId: 3, obtainedMarks: 5, passingMarks: 12,
lessonId: 5, obtainedMarks: 10, passingMarks: 6,
lessonId: 7, obtainedMarks: 13, passingMarks: 8,
lessonId: 11, obtainedMarks: 10, passingMarks: 15,
]
console .log (
addWithoutDups (arr1, arr2)
)
请注意,id 2
和 3
被拒绝为重复,id 11
不合格,但 id 5
和 7
被正确添加。
另请注意,这会返回一个包含您的数据的新数组;它不会改变原件。 (我不会参与这种猥亵的!)
【讨论】:
先生,我想在过滤所有条件后将 id 推送到 arr1。我该怎么办? @AdnanBabai:如果你想改变arr1
,那么你就得问别人了。我总是喜欢使用不可变数据。
@ScottSauyet 在 React 中尝试和变异不是一个好主意。我不知道您的其余代码,但似乎不需要突变 arr1 。只需在答案中使用 concat 或 spread 即可。
@HMR,这是给 OP 的吗?
是的,它是给@AdnanBabai,所以在移动设备上很难阅读,我复制了错误的名称(再次)【参考方案3】:
您创建一个 arr1 课程 ID 的 Set,然后使用数组过滤器过滤掉 arr2 中已经在 arr1 中的所有内容,然后再次过滤以仅获取通过的项目:
//get all lessonId for arr1 in a Set
const arr1Ids = new Set(arr1.map(x=>x.lessonId));
//get items of arr2 that are not already in arr1
const passingArr2NotInArr1 = arr2
.filter(
//take out everything that is already in arr1
item => !arr1Ids.has(item.lessonId)
)
.filter(
//only when it passed
item => item.obtainedMarks >= item.passingMarks
);
【讨论】:
不是什么简单的方法吗? 在 arr1 中有多个具有课程 ID 的对象 @AdnanBabai 仅使用您的代码使用的代码:if (q1.lessonId !== q2.lessonId)
使用 Set 的另一个答案可能更快。
谢谢@HRM。它的工作。你能详细解释一下吗?我在理解方面遇到困难
A Map 拥有 arr1 的所有课程 ID,使用 filter 从 arr2 中取出 arr1 中的课程,然后再次过滤以获取具有足够分数的课程。我会更新我的答案,因为 Set 可能比 map 更好。【参考方案4】:
如果项目相同 -> 它们具有相同的引用,请使用 Set
作为 Sokushinbutsu 的答案
如果没有,请使用Array.prototype.some()
const arr1Difference = arr1.filter((arr1Item) =>
const isSomeInArr2 = arr2.some((arr2Item) =>
return arr1Item.lessonId === arr2Item.lessonId
// return arr1Item === arr2Item (In the case that items are same -> they have same reference)
)
return !isSomeInArr2
)
const arr2AddToArr1Difference = [...arr2, ...arr1Difference ]
【讨论】:
这是一种低效的过滤方式。对于 arr2 中的每个项目,您都在 arr1 中进行查找。以上是关于如何防止数组中的重复项?的主要内容,如果未能解决你的问题,请参考以下文章