如何防止数组中的重复项?

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 23 被拒绝为重复,id 11 不合格,但 id 57 被正确添加。

另请注意,这会返回一个包含您的数据的新数组;它不会改变原件。 (我不会参与这种猥亵的!)

【讨论】:

先生,我想在过滤所有条件后将 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 中进行查找。

以上是关于如何防止数组中的重复项?的主要内容,如果未能解决你的问题,请参考以下文章

从数组列表中删除重复项

如何防止猜数字游戏中的重复猜测?

如何从 Perl 中的数组中删除重复项?

如何使用两个键删除数组中的重复项?

Flash as3 如何删除数组中的重复项?

如何删除数组中的重复项