Adnan Babai
Adnan Babai

Reputation: 65

How to prevent duplicate items in array?

I have two arrays, i want to push some items from arr1 to arr2 preventing duplicates because i've already added some items to arr2 that are also in arr1. i am doing this in 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) => {

                                })
                            }
                        }
                    })
                });

Upvotes: 2

Views: 1074

Answers (4)

HMR
HMR

Reputation: 39270

You create a Set of arr1 lessonId's and then use array filter to filter out everything from arr2 that is already in arr1 and then filter again to get only passing items:

//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
  );

Upvotes: 1

Scott Sauyet
Scott Sauyet

Reputation: 50797

I have no idea what your User.findByIdAndUpdate or $push do, but if you just want to combine the non-duplicated items from the second array in the first, only when the marks comparison works, then you could write something like this:

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)
)

Note that ids 2 and 3 are rejected as duplicates, id 11 fails the qualification, but ids 5 and 7 are added properly.

Also note that this returns a new array with your data; it does not mutate the original. (I won't take part in such obscenities!)

Upvotes: 3

getElementsByName
getElementsByName

Reputation: 131

If items are same -> they have same reference, use Set as the answer of Sokushinbutsu

If not, use 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 ]

Upvotes: 1

Sokushinbutsu
Sokushinbutsu

Reputation: 83

You can use a set instead of an array. They have the built in feature of preventing duplicate entries. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set

Upvotes: 3

Related Questions