这个问题在这里已有答案:
我有一个非常简单的JavaScript数组,可能包含也可能不包含重复项。
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
我需要删除重复项并将唯一值放在一个新数组中。
我可以指出我尝试的所有代码,但我认为它没用,因为它们不起作用。我也接受jQuery解决方案。
使用jQuery快速而肮脏:
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
var uniqueNames = [];
$.each(names, function(i, el){
if($.inArray(el, uniqueNames) === -1) uniqueNames.push(el);
});
像这样使用
Array.filter()
var actualArr = ['Apple', 'Apple', 'Banana', 'Mango', 'Strawberry', 'Banana'];
console.log('Actual Array: ' + actualArr);
var filteredArr = actualArr.filter(function(item, index) {
if (actualArr.indexOf(item) == index)
return item;
});
console.log('Filtered Array: ' + filteredArr);
这可以在ES6中缩短到
actualArr.filter((item,index,self) => self.indexOf(item)==index);
Here是对Array.filter()
的好解释
去这个:
var uniqueArray = duplicateArray.filter(function(elem, pos) {
return duplicateArray.indexOf(elem) == pos;
});
现在uniqueArray不包含重复项。
最简单的一个我到目前为止遇到过。在es6。
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl", "Mike", "Nancy"]
var noDupe = Array.from(new Set(names))
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
我在其他一些问题上做了详细的比较删除,但注意到这是我想在这里分享它的真实地方。
我相信这是最好的方法
var myArray = [100, 200, 100, 200, 100, 100, 200, 200, 200, 200],
reduced = Object.keys(myArray.reduce((p,c) => (p[c] = true,p),{}));
console.log(reduced);
好吧..即使这个是O(n)而其他人都是O(n ^ 2)我很想看到这个缩小/查找表和filter / indexOf组合之间的基准比较(我选择Jeetendras非常好的实现https://stackoverflow.com/a/37441144/4543207) 。我准备一个100K项目数组,填充0-9999范围内的随机正整数,并删除重复项。我重复测试了10次,结果的平均值表明它们的性能不匹配。
好吧到目前为止一切都那么好。但是这次以ES6风格正确地做到了。它看起来很酷..!但截至目前,它对抗强大的解决方案将如何表现对我来说是一个谜。让我们先看看代码,然后对它进行基准测试。
var myArray = [100, 200, 100, 200, 100, 100, 200, 200, 200, 200],
reduced = [...myArray.reduce((p,c) => p.set(c,true),new Map()).keys()];
console.log(reduced);
哇那简短..!但是性能怎么样?这很漂亮......由于过滤器/ indexOf的重量超过了我们的肩膀,我现在可以在0..99999范围内测试一组1M的正整数随机项,以获得10次连续测试的平均值。我可以说这次是一场真正的比赛。亲自看看结果:)
var ranar = [],
red1 = a => Object.keys(a.reduce((p,c) => (p[c] = true,p),{})),
red2 = a => reduced = [...a.reduce((p,c) => p.set(c,true),new Map()).keys()],
avg1 = [],
avg2 = [],
ts = 0,
te = 0,
res1 = [],
res2 = [],
count= 10;
for (var i = 0; i<count; i++){
ranar = (new Array(1000000).fill(true)).map(e => Math.floor(Math.random()*100000));
ts = performance.now();
res1 = red1(ranar);
te = performance.now();
avg1.push(te-ts);
ts = performance.now();
res2 = red2(ranar);
te = performance.now();
avg2.push(te-ts);
}
avg1 = avg1.reduce((p,c) => p+c)/count;
avg2 = avg2.reduce((p,c) => p+c)/count;
console.log("reduce & lut took: " + avg1 + "msec");
console.log("map & spread took: " + avg2 + "msec");
你会用哪一个..?好吧不是那么快......!不要被欺骗。地图处于位移状态。现在看......在上述所有情况下,我们填充一个大小为n的数组,其数量为范围<n。我的意思是我们有一个100的数组,我们填充随机数0..9所以有确定的重复和“几乎”肯定每个数字都有重复。如果我们用随机数0..9999填充大小为100的数组怎么样。我们现在看看家里的地图播放。这次是100K项目的数组,但是随机数范围是0..100M。我们将进行100次连续测试以平均结果。好的,让我们看看赌注..! < - 没有错字
var ranar = [],
red1 = a => Object.keys(a.reduce((p,c) => (p[c] = true,p),{})),
red2 = a => reduced = [...a.reduce((p,c) => p.set(c,true),new Map()).keys()],
avg1 = [],
avg2 = [],
ts = 0,
te = 0,
res1 = [],
res2 = [],
count= 100;
for (var i = 0; i<count; i++){
ranar = (new Array(100000).fill(true)).map(e => Math.floor(Math.random()*100000000));
ts = performance.now();
res1 = red1(ranar);
te = performance.now();
avg1.push(te-ts);
ts = performance.now();
res2 = red2(ranar);
te = performance.now();
avg2.push(te-ts);
}
avg1 = avg1.reduce((p,c) => p+c)/count;
avg2 = avg2.reduce((p,c) => p+c)/count;
console.log("reduce & lut took: " + avg1 + "msec");
console.log("map & spread took: " + avg2 + "msec");
现在这是Map()的壮观复出..!现在可以在你想要删除欺骗时做出更好的决定。
好吧,我们现在都很高兴。但是主角一直伴随着掌声。我相信你们有些人想知道Set对象会做什么。既然我们对ES6持开放态度并且我们知道Map是之前游戏的赢家,那么让我们将Map与Set进行比较。这次典型的皇马对阵巴塞罗那比赛......或者是这样?让我们看看谁将赢得el classico :)
var ranar = [],
red1 = a => reduced = [...a.reduce((p,c) => p.set(c,true),new Map()).keys()],
red2 = a => Array.from(new Set(a)),
avg1 = [],
avg2 = [],
ts = 0,
te = 0,
res1 = [],
res2 = [],
count= 100;
for (var i = 0; i<count; i++){
ranar = (new Array(100000).fill(true)).map(e => Math.floor(Math.random()*10000000));
ts = performance.now();
res1 = red1(ranar);
te = performance.now();
avg1.push(te-ts);
ts = performance.now();
res2 = red2(ranar);
te = performance.now();
avg2.push(te-ts);
}
avg1 = avg1.reduce((p,c) => p+c)/count;
avg2 = avg2.reduce((p,c) => p+c)/count;
console.log("map & spread took: " + avg1 + "msec");
console.log("set & A.from took: " + avg2 + "msec");
哇..男人..!出乎意料的是,它根本没有成为一个经典的。更像是巴塞罗那足球俱乐部对阵CA Osasuna :))
以下内容比列出的jQuery方法快80%以上(参见下面的测试)。这是几年前类似问题的答案。如果我遇到最初提出它的人,我会发布信用证。纯JS。
var temp = {};
for (var i = 0; i < array.length; i++)
temp[array[i]] = true;
var r = [];
for (var k in temp)
r.push(k);
return r;
解决方案1
Array.prototype.unique = function() {
var a = [];
for (i = 0; i < this.length; i++) {
var current = this[i];
if (a.indexOf(current) < 0) a.push(current);
}
return a;
}
解决方案2(使用Set)
Array.prototype.unique = function() {
return Array.from(new Set(this));
}
测试
var x=[1,2,3,3,2,1];
x.unique() //[1,2,3]
性能
当我在chrome中测试两个实现(有和没有Set)的性能时,我发现使用Set的那个实现要快得多!
Array.prototype.unique1 = function() {
var a = [];
for (i = 0; i < this.length; i++) {
var current = this[i];
if (a.indexOf(current) < 0) a.push(current);
}
return a;
}
Array.prototype.unique2 = function() {
return Array.from(new Set(this));
}
var x=[];
for(var i=0;i<10000;i++){
x.push("x"+i);x.push("x"+(i+1));
}
console.time("unique1");
console.log(x.unique1());
console.timeEnd("unique1");
console.time("unique2");
console.log(x.unique2());
console.timeEnd("unique2");
这是一个简单的问题答案。
var names = ["Alex","Tony","James","Suzane", "Marie", "Laurence", "Alex", "Suzane", "Marie", "Marie", "James", "Tony", "Alex"];
var uniqueNames = [];
for(var i in names){
if(uniqueNames.indexOf(names[i]) === -1){
uniqueNames.push(names[i]);
}
}
在ECMAScript 6(又名ECMAScript 2015)中,Set
可用于过滤掉重复项。然后可以使用spread operator将其转换回数组。
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"],
unique = [...new Set(names)];
一种简单但有效的技术,是将filter
方法与过滤器function(value, index){ return this.indexOf(value) == index }
结合使用。
var data = [2,3,4,5,5,4];
var filter = function(value, index){ return this.indexOf(value) == index };
var filteredData = data.filter(filter, data );
document.body.innerHTML = '<pre>' + JSON.stringify(filteredData, null, '\t') + '</pre>';
另见this Fiddle。
最佳答案有O(n²)
的复杂性,但这可以通过使用对象作为哈希只使用O(n)
来完成:
function getDistinctArray(arr) {
var dups = {};
return arr.filter(function(el) {
var hash = el.valueOf();
var isDup = dups[hash];
dups[hash] = true;
return !isDup;
});
}
这适用于字符串,数字和日期。如果您的数组包含复杂对象(即,它们必须与===
进行比较),则上述解决方案将无效。您可以通过在对象本身上设置标志来获取对象的O(n)
实现:
function getDistinctObjArray(arr) {
var distinctArr = arr.filter(function(el) {
var isDup = el.inArray;
el.inArray = true;
return !isDup;
});
distinctArr.forEach(function(el) {
delete el.inArray;
});
return distinctArr;
}
使用Set构造函数和spread syntax:
uniq = [...new Set(array)];
uniqueArray = a.filter(function(item, pos) {
return a.indexOf(item) == pos;
})
基本上,我们迭代数组,并为每个元素检查数组中此元素的第一个位置是否等于当前位置。显然,这两个位置对于重复元素是不同的。
使用过滤器回调的第3个(“this array”)参数,我们可以避免数组变量的闭包:
uniqueArray = a.filter(function(item, pos, self) {
return self.indexOf(item) == pos;
})
虽然简洁,但该算法对于大型阵列(二次时间)并不是特别有效。
function uniq(a) {
var seen = {};
return a.filter(function(item) {
return seen.hasOwnProperty(item) ? false : (seen[item] = true);
});
}
这就是通常的做法。我们的想法是将每个元素放在一个哈希表中,然后立即检查它的存在。这给了我们线性时间,但至少有两个缺点:
uniq([1,"1"])
将只返回[1]
uniq([{foo:1},{foo:2}])
将仅返回[{foo:1}]
。也就是说,如果你的数组只包含基元并且你不关心类型(例如它总是数字),那么这个解决方案是最佳的。
通用解决方案结合了两种方法:它使用基元的哈希查找和对象的线性搜索。
function uniq(a) {
var prims = {"boolean":{}, "number":{}, "string":{}}, objs = [];
return a.filter(function(item) {
var type = typeof item;
if(type in prims)
return prims[type].hasOwnProperty(item) ? false : (prims[type][item] = true);
else
return objs.indexOf(item) >= 0 ? false : objs.push(item);
});
}
另一种选择是先对数组进行排序,然后删除与前一个元素相等的每个元素:
function uniq(a) {
return a.sort().filter(function(item, pos, ary) {
return !pos || item != ary[pos - 1];
})
}
同样,这不适用于对象(因为sort
的所有对象都相同)。另外,我们默默地改变原始阵列作为副作用 - 不好!但是,如果您的输入已经排序,则可以采用此方法(只需从上面删除sort
)。
有时需要根据除了相等之外的某些标准来统一列表,例如,过滤掉不同的对象,但共享一些属性。这可以通过传递回调来优雅地完成。此“键”回调应用于每个元素,并删除具有相同“键”的元素。由于key
预计会返回一个原语,哈希表在这里可以正常工作:
function uniqBy(a, key) {
var seen = {};
return a.filter(function(item) {
var k = key(item);
return seen.hasOwnProperty(k) ? false : (seen[k] = true);
})
}
一个特别有用的key()
是JSON.stringify
,它将删除物理上不同的物体,但“看起来”相同:
a = [[1,2,3], [4,5,6], [1,2,3]]
b = uniqBy(a, JSON.stringify)
console.log(b) // [[1,2,3], [4,5,6]]
如果key
不是原始的,你必须求助于线性搜索:
function uniqBy(a, key) {
var index = [];
return a.filter(function (item) {
var k = key(item);
return index.indexOf(k) >= 0 ? false : index.push(k);
});
}
在ES6中,您可以使用Set
:
function uniqBy(a, key) {
let seen = new Set();
return a.filter(item => {
let k = key(item);
return seen.has(k) ? false : seen.add(k);
});
}
或者Map
:
function uniqBy(a, key) {
return [
...new Map(
a.map(x => [key(x), x])
).values()
]
}
它们也适用于非原始键。
通过键删除对象时,您可能希望保留第一个“相等”对象或最后一个对象。
使用上面的Set
变体保留第一个,而Map
保留最后一个:
function uniqByKeepFirst(a, key) {
let seen = new Set();
return a.filter(item => {
let k = key(item);
return seen.has(k) ? false : seen.add(k);
});
}
function uniqByKeepLast(a, key) {
return [
...new Map(
a.map(x => [key(x), x])
).values()
]
}
//
data = [
{a:1, u:1},
{a:2, u:2},
{a:3, u:3},
{a:4, u:1},
{a:5, u:2},
{a:6, u:3},
];
console.log(uniqByKeepFirst(data, it => it.u))
console.log(uniqByKeepLast(data, it => it.u))
underscore和Lo-Dash都提供uniq
方法。他们的算法基本上类似于上面的第一个片段,归结为:
var result = [];
a.forEach(function(item) {
if(result.indexOf(item) < 0) {
result.push(item);
}
});
这是二次的,但还有很好的额外好处,比如包装原生的indexOf
,通过键(iteratee
用他们的说法)进行统一的能力,以及已经排序的数组的优化。
如果你正在使用jQuery并且在它之前没有一美元就无法忍受任何事情,那就是这样的:
$.uniqArray = function(a) {
return $.grep(a, function(item, pos) {
return $.inArray(item, a) === pos;
});
}
这也是第一个片段的变体。
函数调用在JavaScript中很昂贵,因此上述解决方案虽然简洁,但效率不高。为了获得最佳性能,请将filter
替换为循环并删除其他函数调用:
function uniq_fast(a) {
var seen = {};
var out = [];
var len = a.length;
var j = 0;
for(var i = 0; i < len; i++) {
var item = a[i];
if(seen[item] !== 1) {
seen[item] = 1;
out[j++] = item;
}
}
return out;
}
这段丑陋的代码与上面的代码段#3相同, 但要快一个数量级 (截至2017年,它只有两倍的速度 - JS核心人员做得很好!)
function uniq(a) {
var seen = {};
return a.filter(function(item) {
return seen.hasOwnProperty(item) ? false : (seen[item] = true);
});
}
function uniq_fast(a) {
var seen = {};
var out = [];
var len = a.length;
var j = 0;
for(var i = 0; i < len; i++) {
var item = a[i];
if(seen[item] !== 1) {
seen[item] = 1;
out[j++] = item;
}
}
return out;
}
/////
var r = [0,1,2,3,4,5,6,7,8,9],
a = [],
LEN = 1000,
LOOPS = 1000;
while(LEN--)
a = a.concat(r);
var d = new Date();
for(var i = 0; i < LOOPS; i++)
uniq(a);
document.write('<br>uniq, ms/loop: ' + (new Date() - d)/LOOPS)
var d = new Date();
for(var i = 0; i < LOOPS; i++)
uniq_fast(a);
document.write('<br>uniq_fast, ms/loop: ' + (new Date() - d)/LOOPS)
ES6提供了Set对象,这使事情变得更加容易:
function uniq(a) {
return Array.from(new Set(a));
}
要么
let uniq = a => [...new Set(a)];
请注意,与python不同,ES6集按插入顺序迭代,因此此代码保留原始数组的顺序。
但是,如果您需要一个包含唯一元素的数组,为什么不从一开始就使用集合?
可以在相同的基础上构建基于生成器的uniq
“懒惰”版本:
function* uniqIter(a) {
let seen = new Set();
for (let x of a) {
if (!seen.has(x)) {
seen.add(x);
yield x;
}
}
}
// example:
function* randomsBelow(limit) {
while (1)
yield Math.floor(Math.random() * limit);
}
// note that randomsBelow is endless
count = 20;
limit = 30;
for (let r of uniqIter(randomsBelow(limit))) {
console.log(r);
if (--count === 0)
break
}
// exercise for the reader: what happens if we set `limit` less than `count` and why
所以选项是:
let a = [11,22,11,22];
let b = []
b = [ ...new Set(a) ];
// b = [11, 22]
b = Array.from( new Set(a))
// b = [11, 22]
b = a.filter((val,i)=>{
return a.indexOf(val)==i
})
// b = [11, 22]
这里是没有任何特殊库的简单方法是特殊功能,
name_list = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
get_uniq = name_list.filter(function(val,ind) { return name_list.indexOf(val) == ind; })
console.log("Original name list:"+name_list.length, name_list)
console.log("\n Unique name list:"+get_uniq.length, get_uniq)
除了比当前答案(减去未来的ES6)更简单,更简洁的解决方案之外,我还对此进行了测试,并且速度也快得多:
var uniqueArray = dupeArray.filter(function(item, i, self){
return self.lastIndexOf(item) == i;
});
一个警告:在IE9中添加了Array.lastIndexOf(),所以如果你需要低于它,你需要寻找其他地方。
以下是ES2015的通用且严格功能的方法:
// small, reusable auxiliary functions
const apply = f => a => f(a);
const flip = f => b => a => f(a) (b);
const uncurry = f => (a, b) => f(a) (b);
const push = x => xs => (xs.push(x), xs);
const foldl = f => acc => xs => xs.reduce(uncurry(f), acc);
const some = f => xs => xs.some(apply(f));
// the actual de-duplicate function
const uniqueBy = f => foldl(
acc => x => some(f(x)) (acc)
? acc
: push(x) (acc)
) ([]);
// comparators
const eq = y => x => x === y;
// string equality case insensitive :D
const seqCI = y => x => x.toLowerCase() === y.toLowerCase();
// mock data
const xs = [1,2,3,1,2,3,4];
const ys = ["a", "b", "c", "A", "B", "C", "D"];
console.log( uniqueBy(eq) (xs) );
console.log( uniqueBy(seqCI) (ys) );
我们可以很容易地从unique
派生unqiueBy
或使用Set
s更快的实现:
const unqiue = uniqueBy(eq);
// const unique = xs => Array.from(new Set(xs));
这种方法的好处:
uniqueBy
不像带有循环的命令式实现那么快,但由于它的通用性,它更具表现力。
如果您在应用中将uniqueBy
识别为具体性能损失的原因,请将其替换为优化代码。也就是说,首先以功能性的声明方式编写代码。之后,如果遇到性能问题,请尝试优化位置的代码,这是导致问题的原因。
uniqueBy
利用隐藏在其体内的突变(push(x) (acc)
)。它重用累加器而不是在每次迭代后丢弃它。这减少了内存消耗和GC压力。由于这种副作用包含在函数内部,因此外部的所有内容都保持纯净。
在任何地方(甚至在PhotoshopScript中)代码中理解和工作都非常简单。核实!
var peoplenames = new Array("Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl");
peoplenames = unique(peoplenames);
alert(peoplenames);
function unique(array){
var len = array.length;
for(var i = 0; i < len; i++) for(var j = i + 1; j < len; j++)
if(array[j] == array[i]){
array.splice(j,1);
j--;
len--;
}
return array;
}
//*result* peoplenames == ["Mike","Matt","Nancy","Adam","Jenny","Carl"]
for (i=0; i<originalArray.length; i++) {
if (!newArray.includes(originalArray[i])) {
newArray.push(originalArray[i]);
}
}
$(document).ready(function() {
var arr1=["dog","dog","fish","cat","cat","fish","apple","orange"]
var arr2=["cat","fish","mango","apple"]
var uniquevalue=[];
var seconduniquevalue=[];
var finalarray=[];
$.each(arr1,function(key,value){
if($.inArray (value,uniquevalue) === -1)
{
uniquevalue.push(value)
}
});
$.each(arr2,function(key,value){
if($.inArray (value,seconduniquevalue) === -1)
{
seconduniquevalue.push(value)
}
});
$.each(uniquevalue,function(ikey,ivalue){
$.each(seconduniquevalue,function(ukey,uvalue){
if( ivalue == uvalue)
{
finalarray.push(ivalue);
}
});
});
alert(finalarray);
});
如果您有任何机会使用
D3.js
你可以做到
d3.set(["foo", "bar", "foo", "baz"]).values() ==> ["foo", "bar", "baz"]
略微修改了thg435使用自定义比较器的出色答案:
function contains(array, obj) {
for (var i = 0; i < array.length; i++) {
if (isEqual(array[i], obj)) return true;
}
return false;
}
//comparator
function isEqual(obj1, obj2) {
if (obj1.name == obj2.name) return true;
return false;
}
function removeDuplicates(ary) {
var arr = [];
return ary.filter(function(x) {
return !contains(arr, x) && arr.push(x);
});
}
这可能是从数组中永久删除重复项的最快方法之一,比此处的大多数函数快10倍。在safari中快78倍
function toUnique(a,b,c){ //array,placeholder,placeholder
b=a.length;while(c=--b)while(c--)a[b]!==a[c]||a.splice(c,1)
}
如果你不能阅读上面的代码问,请阅读一本javascript书或者这里有一些关于更短代码的解释。 https://stackoverflow.com/a/25082874/2450730
厌倦了看到所有使用for循环或jQuery的坏例子。 Javascript现在拥有完美的工具:排序,映射和缩小。
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
var uniq = names.reduce(function(a,b){
if (a.indexOf(b) < 0 ) a.push(b);
return a;
},[]);
console.log(uniq, names) // [ 'Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Carl' ]
// one liner
return names.reduce(function(a,b){if(a.indexOf(b)<0)a.push(b);return a;},[]);
可能有更快的方法,但这个很不错。
var uniq = names.slice() // slice makes copy of array before sorting it
.sort(function(a,b){
return a > b;
})
.reduce(function(a,b){
if (a.slice(-1)[0] !== b) a.push(b); // slice(-1)[0] means last item in array without removing it (like .pop())
return a;
},[]); // this empty array becomes the starting value for a
// one liner
return names.slice().sort(function(a,b){return a > b}).reduce(function(a,b){if (a.slice(-1)[0] !== b) a.push(b);return a;},[]);
在ES6中,你有集合和传播,这使得删除所有重复项非常容易和高效:
var uniq = [ ...new Set(names) ]; // [ 'Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Carl' ]
有人询问是根据有多少个唯一名称来排序结果:
var names = ['Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Nancy', 'Carl']
var uniq = names
.map((name) => {
return {count: 1, name: name}
})
.reduce((a, b) => {
a[b.name] = (a[b.name] || 0) + b.count
return a
}, {})
var sorted = Object.keys(uniq).sort((a, b) => uniq[a] < uniq[b])
console.log(sorted)
https://stackoverflow.com/a/21353032/2450730
https://jsfiddle.net/2w0k5tz8/
循环,删除重复项,并创建克隆数组占位符,因为不会更新数组索引。
向后循环以获得更好的性能(您的循环不需要继续检查数组的长度)
Vanilla JS:使用类似Set的对象删除重复项
您始终可以尝试将其放入对象中,然后迭代其键:
function remove_duplicates(arr) {
var obj = {};
var ret_arr = [];
for (var i = 0; i < arr.length; i++) {
obj[arr[i]] = true;
}
for (var key in obj) {
ret_arr.push(key);
}
return ret_arr;
}
Vanilla JS:通过跟踪已经看到的值来删除重复项(订单安全)
或者,对于订单安全版本,使用对象存储所有先前看到的值,并在添加到数组之前检查它的值。
function remove_duplicates_safe(arr) {
var seen = {};
var ret_arr = [];
for (var i = 0; i < arr.length; i++) {
if (!(arr[i] in seen)) {
ret_arr.push(arr[i]);
seen[arr[i]] = true;
}
}
return ret_arr;
}
ECMAScript 6:使用新的Set数据结构(订单安全)
ECMAScript 6添加了新的Set
数据结构,它允许您存储任何类型的值。 Set.values
以插入顺序返回元素。
function remove_duplicates_es6(arr) {
let s = new Set(arr);
let it = s.values();
return Array.from(it);
}
用法示例:
a = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
b = remove_duplicates(a);
// b:
// ["Adam", "Carl", "Jenny", "Matt", "Mike", "Nancy"]
c = remove_duplicates_safe(a);
// c:
// ["Mike", "Matt", "Nancy", "Adam", "Jenny", "Carl"]
d = remove_duplicates_es6(a);
// d:
// ["Mike", "Matt", "Nancy", "Adam", "Jenny", "Carl"]
它是一个包含许多用于操作数组的函数的库。
这与jQuery的tux以及Backbone.js的吊带相关。
_.uniq(array, [isSorted], [iterator])
别名:独特 生成数组的无副本版本,使用===来测试对象相等性。如果您事先知道数组已排序,则为isSorted传递true将运行更快的算法。如果要基于转换计算唯一项,请传递迭代器函数。
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
alert(_.uniq(names, false));
注意:Lo-Dash(underscore的竞争对手)也提供了类似的.uniq实现。
使用数组过滤器和indexOf函数的单行版本:
arr = arr.filter (function (value, index, array) {
return array.indexOf (value) == index;
});
您可以使用filter
方法的第二个 - index - 参数,在JavaScript中执行此操作:
var a = [2,3,4,5,5,4];
a.filter(function(value, index){ return a.indexOf(value) == index });
或者简而言之
a.filter((v,i) => a.indexOf(v) == i)
一条线:
let names = ['Mike','Matt','Nancy','Adam','Jenny','Nancy','Carl', 'Nancy'];
let dup = [...new Set(names)];
console.log(dup);
使用本机javascript函数从数组中删除重复项的最简洁方法是使用如下序列:
vals.sort().reduce(function(a, b){ if (b != a[0]) a.unshift(b); return a }, [])
在reduce函数中不需要slice
和indexOf
,就像我在其他例子中看到的那样!然而,将它与过滤器功能一起使用是有意义的:
vals.filter(function(v, i, a){ return i == a.indexOf(v) })
另一种已经在少数浏览器上运行的ES6(2015)方法是:
Array.from(new Set(vals))
甚至使用spread operator:
[...new Set(vals)]
干杯!