How to create a set from an array and remove the original elements in JavaScript

I have an array with duplicate values.

I want to create a Set to get the different values ​​of this array and delete or create a new array that will have the same MINUS data as the elements needed to create the Set.

This is not just removing duplicates, but removing SINGLE records of each individual value in the original array

Something like this works, but I wonder if there is a more direct approach:

let originalValues = [ 'a', 'a', 'a', 'b', 'b', 'c', 'c', 'd' ]; let distinct = new Set(originalValues); /* distinct -> { 'a', 'b', 'c', 'd' } */ // Perhaps originalValues.extract(distinct) ?? for (let val of distinct.values()) { const index = originalValues.indexOf(val); originalValues.splice(index, 1); } /* originalValues -> [ 'a', 'a', 'b', 'c' ]; */ 
+6
source share
6 answers

You can use closure over Set and check for availability.

 let originalValues = ['a', 'a', 'a', 'b', 'b', 'c', 'c', 'd'], result = originalValues.filter((s => a => s.has(a) || !s.add(a))(new Set)); console.log(result); 
+3
source

Use Array#filter in combination with Set :

 const originalValues = ['a', 'a', 'a', 'b', 'b', 'c', 'c', 'd']; const remainingValues = originalValues.filter(function(val) { if (this.has(val)) { // if the Set has the value this.delete(val); // remove it from the Set return false; // filter it out } return true; }, new Set(originalValues)); console.log(remainingValues); 
+5
source

You should not use indexOf inside the loop because it has a linear value and the total value becomes quadratic. What I would like to do is use a map to count the occurrences of each element in your array, and then convert back to an array, subtracting one occurrence.

 let originalValues = ['a', 'a', 'a', 'b', 'b', 'c', 'c', 'd']; let freq = new Map(); // frequency table for (let item of originalValues) if (freq.has(item)) freq.set(item, freq.get(item)+1); else freq.set(item, 1); var arr = []; for (let [item,count] of freq) for (let i=1; i<count; ++i) arr.push(item); console.log(arr); 

If all elements are strings, you can use a simple object instead of a map.

+2
source

You can create a simple Array.prototype.reduce with a hash table to count the number of occurrences and populate the result only if it occurs more than once.

See the demo below:

 var originalValues=['a','a','a','a','b','b','b','c','c','d']; var result = originalValues.reduce(function(hash) { return function(p,c) { hash[c] = (hash[c] || 0) + 1; if(hash[c] > 1) p.push(c); return p; }; }(Object.create(null)), []); console.log(result); 
 .as-console-wrapper{top:0;max-height:100%!important;} 
+1
source

Instead of using Set for this, you can simply use reduce() and create a new array with unique values, as well as update the original array with splice() .

 let oV = ["a", "a", "a", "a", "b", "b", "c", "c", "d"] var o = {} var distinct = oV.reduce(function(r, e) { if (!o[e]) o[e] = 1 && r.push(e) && oV.splice(oV.indexOf(e), 1) return r; }, []) console.log(distinct) console.log(oV) 
+1
source

As an alternative approach, you can use the following algorithm, which will delete only the 1st record of the duplicate element. If it is not duplicated, it will not delete anything.

 const originalValues = ['a', 'a', 'a', 'b', 'b', 'c', 'c', 'd']; var r = originalValues.reduce(function(p, c, i, a) { var lIndex = a.lastIndexOf(c); var index = a.indexOf(c) if (lIndex === index || index !== i) p.push(c); return p }, []) console.log(r) 

If duplicates are not the case, you can directly remove the first iteration directly

 const originalValues = ['a', 'a', 'a', 'b', 'b', 'c', 'c', 'd']; var r = originalValues.filter(function(el, i) { return originalValues.indexOf(el) !== i }) console.log(r) 
+1
source

Source: https://habr.com/ru/post/1013879/


All Articles