admin管理员组文章数量:1389762
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.
This is not just a matter of remove the duplicates, but remove a SINGLE entry of a each distinct value in the original array
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'
];
*/
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.
This is not just a matter of remove the duplicates, but remove a SINGLE entry of a each distinct value in the original array
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'
];
*/
Share
Improve this question
edited Jan 8, 2017 at 14:56
Lucas Ricoy
asked Jan 8, 2017 at 14:45
Lucas RicoyLucas Ricoy
1631 silver badge8 bronze badges
8
-
1
If
originalValues
starts with'a', 'a', 'a'
, should it end with'a', 'a'
or just'a'
? – Ry- ♦ Commented Jan 8, 2017 at 14:46 -
It should just remove one, so
'a', 'a'
– Lucas Ricoy Commented Jan 8, 2017 at 14:50 - 1 Reopening because this is about removing elements that appear in the set, not about removing duplicates. – Oriol Commented Jan 8, 2017 at 14:54
-
1
originalValues.splice(index, 1);
? – dandavis Commented Jan 8, 2017 at 14:55 -
1
in that code, watch out for splicing (w/remove) an index of
-1
, that can ruin your day! – dandavis Commented Jan 8, 2017 at 14:57
6 Answers
Reset to default 5Use Array#filter
in bination with the 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 could use closure over a Set
and check for existence.
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);
You should not use indexOf
inside a loop, because it has linear cost, and the total cost bees quadratic. 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.
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()
.
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)
本文标签: How to create a Set from Array and remove original items in JavaScriptStack Overflow
版权声明:本文标题:How to create a Set from Array and remove original items in JavaScript - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744720917a2621687.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论