18

I received this question for practice and the wording confused me, as I see 2 results that it might want.

And either way, I'd like to see both solutions.

For example, if I have an array:

let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10]; 

I'm taking this as wanting the final result as either:

let finalResult = [1, 2, 3, 4, 5, 8, 9, 10]; 

OR:

let finalResult = [1, 9, 10]; 

The difference between the two being, one just removes any duplicate numbers and leaves the rest and the second just wants any number that isn't a duplicate.

Either way, I'd like to write two functions that does one of each.

This, given by someone else gives my second solution.

let elems = {}, arr2 = arr.filter(function (e) { if (elems[e] === undefined) { elems[e] = true; return true; } return false; }); console.log(arr2); 

I'm not sure about a function for the first one (remove all duplicates).

3
  • If you're using lodash, you can use _.uniq() Commented Mar 20, 2019 at 9:29
  • 2
    Further, this is asking for the inverse of Get all non-unique values (i.e.: duplicate/more than one occurrence) in an array. Finally, this post is asking two separate questions and both have good answers elsewhere already. Commented Mar 20, 2019 at 9:51
  • To answer the question "which one is it" in a comment-answer: if you're asked to remove duplicates, I believe you should understand the first variant. The second variant removes all element that have duplicates, meaning the "original" value AND its duplicates. Commented Mar 20, 2019 at 13:18

9 Answers 9

26

Using Set and Array.from()

let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10]; console.log(Array.from(new Set(arr)));

Alternate using regex

regex explanation here

let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10]; let res = arr .join(',') .replace(/(\b,\w+\b)(?=.*\1)/ig, '') .split(',') .map(Number); console.log(res);

Alternate using objects

let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10]; let obj = arr.reduce((acc, val) => Object.assign(acc, { [val]: val }), {}); console.log(Object.values(obj));

Sign up to request clarification or add additional context in comments.

Comments

13

Just use a simple array.filter one-liner:

let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10]; let finalResult = arr.filter((e, i, a) => a.indexOf(e) == i).sort(function(a, b){return a - b}); console.log(finalResult);

You could use another filter statement if you wanted the second result:

let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10]; let finalResult = arr.filter((e, i, a) => a.filter(f => f == e).length == 1).sort(function(a, b){return a - b}); console.log(finalResult);

5 Comments

You could also add .sort() to sort them by numerical order: .sort(function(a, b){return a - b}) on finalresult
Yes @Mukyuu, that would also be useful
Worth pointing out that the run time of this approach will be quadratic on the size of the input, which is probably not great unless the input arrays are known to be always fairly small.
Most voted with multiple array#filter, array#sort and array#indexOf... That is not performant
Do note that the .sort() is not necessary - the end result without the sort is still an array without any duplicate items, just in the same order as the original array. (It does make it exactly match the finalResult variable in the question though.)
12

For the first part you can use Set() and Spread Syntax to remove duplicates.

let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10]; let res = [...new Set(arr)] console.log(res)

For the second part you can use reduce()

let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10]; //to get the object with count of each number in array. let obj = arr.reduce((ac,a) => { //check if number doesnot occur before then set its count to 1 if(!ac[a]) ac[a] = 1; //if number is already in object increase its count else ac[a]++; return ac; },{}) //Using reduce on all the keys of object means all numbers. let res = Object.keys(obj).reduce((ac,a) => { //check if count of current number 'a' is `1` in the above object then add it into array if(obj[a] === 1) ac.push(+a) return ac; },[]) console.log(res)

6 Comments

nice appreciate that, that 2nd one looks crazy. I'm assuming the time complexity for would be less than ideal compared to other results?
@mph85 Yes its a little complex because it doesnot go through the array again and again instead it just store all the result obj and then filter it.Its better regarding performance
could you remind me why we need the spread operator? what happens if we don't have it? @Maheer Ali
Is it because if we don't have it, it'll just log an object?
@mph85 No if we will not have it. We will have a Set() inside array. We use it convert Set() to Array
|
5

You can use closure and Map

let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10]; const build = ar => { const mapObj = ar.reduce((acc, e) => { acc.has(e) ? acc.set(e, true) : acc.set(e, false) return acc }, new Map()) return function(hasDup = true) { if(hasDup) return [...mapObj.keys()] else return [...mapObj].filter(([key, val]) => !val).map(([k, v])=> k) } } const getArr = build(arr) console.log(getArr()) console.log(getArr(false))

Comments

5

You can create both arrays in One Go

let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10]; let unique = new Set(); let repeated = Array.from(arr.reduce((acc, curr) => {	acc.has(curr) ? unique.delete(curr) : acc.add(curr) && unique.add(curr);	return acc; }, new Set())); console.log(Array.from(unique)) console.log(repeated)

2 Comments

Nice one mate +1
I wonder if the ternary plus && could be unclear though (x?y:z&&w)? It's not obvious to me how JS's order of operations would handle that, and I wonder if you could get across the same logic and reasoning by using if/else?
5

You can use Array.prototype.reduce() create a hash object where the keys are the numbers in the array and the values are going to be the the repeated occurrence of numbers in the arr array variable..

Then using Object.keys():

  • Remove all duplicates Object.keys(hash)
  • Remove all duplicates but filtering with Array.prototype.filter() to get the numbers with only one occurrence

Code:

const arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10]; const hash = arr.reduce((a, c) => (a[c] = (a[c] || 0) + 1, a), {}); // [1, 2, 3, 4, 5, 8, 9, 10]; const finalResultOne = Object.keys(hash); // [1, 9, 10]; const finalResultTwo = Object.keys(hash).filter(k => hash[k] === 1); console.log('finalResultOne:', ...finalResultOne); console.log('finalResultTwo:', ...finalResultTwo);

Comments

4

You could sort the array before and filter the array by checking only one side for duplicates or both sides.

var array = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10], result1, result2; array.sort((a, b) => a - b); result1 = array.filter((v, i, a) => a[i - 1] !== v); result2 = array.filter((v, i, a) => a[i - 1] !== v && a[i + 1] !== v); console.log(...result1); console.log(...result2)

5 Comments

thank for that, for the result1 what is going on with the a[i - 1] !== v?
a is the array, i is the actual index, and v is the actual value. it takes the value from the index before of the actual index and looks if the values are not equal.
ah ok, and sorry, it takes the value from the index before of the actual index? Not sure what you mean by that
for example if you have the value 9 of the array as v, then the value before is 8.
ah ok, thank you for that
4

As many other have said, the first one is just [...new Set(arr)]

For the second, just filter out those that occur more than once:

const arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10]; const count = (arr, e) => arr.filter(n => n == e).length const unique = arr => arr.filter(e => count(arr, e) < 2) console.log(unique(arr));

Comments

2

var arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10]; var map = {}; var finalResult = []; for (var i = 0; i < arr.length; i++) { if (!map.hasOwnProperty(arr[i])) { map[arr[i]] = true; finalResult.push(arr[i]); } } //if you need it sorted otherwise it will be in order finalResult.sort(function(a, b) { return a - b }); console.log(finalResult);

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.