3

Say I have

arr1 = ["Tom","Harry","Patrick"]

arr2 = ["Miguel","Harry","Patrick","Felipe","Mario","Tom"]

How can I remove the duplicate elements in arrays?

I want this output

arr2 = ["Miguel","Felipe","Mario"]
Emeeus
  • 5,072
  • 2
  • 25
  • 37
User100696
  • 687
  • 4
  • 12
  • 26
  • Please paste your code what you have tried. – samnu pel Sep 05 '18 at 22:28
  • Possible duplicate of [Get all unique values in a JavaScript array (remove duplicates)](https://stackoverflow.com/questions/1960473/get-all-unique-values-in-a-javascript-array-remove-duplicates) – imans77 Sep 05 '18 at 22:29
  • Possible duplicate of [Merge two arrays](https://stackoverflow.com/questions/1584370/how-to-merge-two-arrays-in-javascript-and-de-duplicate-items) – lietutis Sep 05 '18 at 22:30

9 Answers9

3

Use filter combined with includes. Example:

let arr1 = ["Tom","Harry","Patrick"]
let arr2 = ["Miguel","Harry","Patrick","Felipe","Mario","Tom"]
arr2 = arr2.filter(x=>!arr1.includes(x))
console.log(arr2)
basarat
  • 261,912
  • 58
  • 460
  • 511
1

If you have lodash, you can use the difference function directly.

_.difference(arr2, arr1) will give the required output.

Edit: JSFiddle URL: https://jsfiddle.net/k3ynjq1m/3/

user2133404
  • 1,816
  • 6
  • 34
  • 60
1

I think that the best way will be to use filter() array method, iterate through the target array (it's arr2 in this case), and exclude duplicates via !arr1.includes(currentItem). This construction lets you know, does arr1 contain current item of iteration:

const arr1 = ["Tom","Harry","Patrick"];
const arr2 = ["Miguel","Harry","Patrick","Felipe","Mario","Tom"];

const result = arr2.filter(d => !arr1.includes(d));
console.log(result);
P.S.
  • 15,970
  • 14
  • 62
  • 86
1

Using includes() is better because returns true or false, but unfortunately it is not supported by IE, see this. In case you want this working on IE too, you should use indexOf().

var arr1 = ["Tom","Harry","Patrick"]

var arr2 = ["Miguel","Harry","Patrick","Felipe","Mario","Tom"]

arr2 = arr2.filter(e=>arr1.indexOf(e)<0)

console.log(arr2)

And filter is better because:

The filter() method creates a new array with all elements that pass the test implemented by the provided function.

Emeeus
  • 5,072
  • 2
  • 25
  • 37
0

Using regular js, you can use a nested for loop:

for (var i in arr2) {
  var duplicate = false;
  for (var i2 in arr1) {
    if (arr2[i] == arr1.[i2]) {
      duplicate = true;
    }
  }
  if (duplicate) {
    arr2.splice(i, 1);
  }
}
Kevin Lewis
  • 231
  • 1
  • 8
0

I think you should keep a map and add elements to that map.

if element exists in map, then that is duplicate else add it to map.

The way you can store your duplicates is storing their value in another list. That is up to you.

Once you know your duplicates, duplicate it from the list.

This is O(n) complexity, and O(n) space complexity.

thenakulchawla
  • 5,024
  • 7
  • 30
  • 42
0
for(var i = 0 ; i<this.arr1.length; i++) {
    for(var j = 0 ; j<this.arr2.length; j++) {
        if(this.arr1[i] === this.arr2[j]) {
            this.arr1.splice(i, 1);
            this.arr2.splice(j, 1);
                i--;
                j--;
        }
    }
}    
this.arr2 = this.arr1.concat(this.arr2);
console.log(this.arr2)

here's a working code (your exemple): https://stackblitz.com/edit/angular-yzte87

Ayoub k
  • 7,788
  • 9
  • 34
  • 57
0

So the way I see it there are multiple ways to achieve what you're looking for,

  1. Using filter and include like some mentioned above me - It will work but I don't know how efficient that will be as you are using filter to iterate on arr2 and then for each element you iterate on arr1 to see if there's matching case, I don't know how familiar you are with algorithm analysis but it's O(N power 2) which is not very time efficient, means quickly as arr1 or arr2 will grow it will take much longer for your function to run, if you do go with that option please use sort() first so you might save time and be more efficient.

See Example:

  let namesToRemove = ["Tom", "Harry", "Patrick"].sort()
  let names = ["Miguel", "Harry", "Patrick", "Felipe", "Mario", "Tom"].sort()

  let lastNameToRemove = namesToRemove[namesToRemove.length - 1]

  names = names.filter((name) => {
    if (name[0] > lastNameToRemove[0]) {
      return true
    }

    return !namesToRemove.includes(name)
  })

  console.log(names)

Keep in mind that if you will use for loop and splice() you can just break and it will be even more efficient.

  1. Using Map - You can iterate once on your first array and create a map in JS which is just using an object notation and once on your names array and check if there is a match, you can improve that using sort() and other improvement but the idea is, see below example.

See Example:

  let namesToRemove = ["Tom", "Harry", "Patrick"]
  let names = ["Miguel", "Harry", "Patrick", "Felipe", "Mario", "Tom"]

  let namesToRemoveMap = {}

  for (name of namesToRemove) {
    namesToRemoveMap[name] = true
  }

  names = names.filter((name) => !namesToRemoveMap[name])

  console.log(names)

Of course either way you choose I would include some more defensive checks, like if the arrays have value in them etc...

Hope I could explain myself clear, let me know if you need more help or if you have any question.

LiaVinci
  • 1
  • 2
0

So you want to remove elements from an array (if they exist) based from another array. Ok, let see... I have a component that implement a function with a similar logic:

let criteriaArr = ["Tom", "Harry", "Patrick"];
let arrToFilter = ["Miguel","Harry","Patrick","Felipe","Mario","Tom"];

let filteredArray = arrToFilter.filter(e => criteriaArr.indexOf(e) < 0);

console.log(filteredArray);

So what filter does is: Returns the elements of an array that meet the condition specified in a callback function.

what the callback function does is: for each element from arrToFilter, if that element does not exit in criteriaArr then keep it otherwise go to the next element.

Here is the function:

removeElems(arrToFilter: Array<any>): Array<any> {
  let filteredArray = arrToFilter.filter(e => this._criteriaArr.indexOf(e) < 0);
  return filteredArray;
}

this._criteriaArr is a private property with default value: private _criteriaArr = ["Tom","Harry","Patrick"]

Or, you can do it this way:

removeElems(arrToFilter: Array<any>, criteriaArr: Array<any>): Array<any> {
  let filteredArray = arrToFilter.filter(e => criteriaArr.indexOf(e) < 0);
  return filteredArray;
}

handle it with two array.

have fun ! :)

Sinan
  • 898
  • 1
  • 9
  • 23