[英]How to create a Set from Array and remove original items in JavaScript
I have an Array with duplicate values. 我有一个重复值的数组。
I want to create a Set to get the distinct values of that array and remove or create a new Array that will have the same data MINUS the elements required to create the Set. 我想创建一个Set来获取该数组的不同值,并删除或创建一个新的Array,它将具有相同的数据MINUS创建Set所需的元素。
This is not just a matter of remove the duplicates, but remove a SINGLE entry of a each distinct value in the original array 这不仅仅是删除重复项,而是删除原始数组中每个不同值的SINGLE条目
Something like that 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'
];
*/
Use Array#filter
in combination with the Set
: 将
Array#filter
与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);
You should not use indexOf
inside a loop, because it has linear cost, and the total cost becomes quadratic. 您不应该在循环中使用
indexOf
,因为它具有线性成本,并且总成本变为二次方。 What I would do is use a map to count the occurrences of each item 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 items are strings you can use a plain object instead of a map. 如果所有项都是字符串,则可以使用普通对象而不是地图。
You can create a simple Array.prototype.reduce
loop with a hash table
to count the number of occurrences and populate the result only if it occurs more than once. 您可以使用
hash table
创建一个简单的Array.prototype.reduce
循环来计算出现次数,并仅在多次出现时填充结果 。
See 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;}
Instead of using Set for this you could just use reduce()
and create new array with unique values and also update original array with splice()
. 您可以使用
reduce()
并使用唯一值创建新数组,并使用splice()
更新原始数组,而不是使用Set。
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)
As an alternate approach, you can use following algorithm that will remove only 1st entry of a duplicate element. 作为替代方法,您可以使用以下算法,该算法仅删除重复元素的第一个条目。 If not duplicate, it will not remove 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 case, then you can directly remove 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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.