从JS数组中删除重复值

uin 发布于 2018-12-25 arrays 最后更新 2018-12-25 11:58 189 浏览

我有一个非常简单的JavaScript数组,可能包含或不包含重复项。

names = new Array("Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl");
我需要删除重复项并将唯一值放入新数组中。 我可以指出我尝试过的所有代码,但我认为这是无用的,因为它们不起作用。我也接受jQuery解决方案。

类似问题:

已邀请:

tvel

赞同来自:

嵌套循环方法,用于删除数组中的重复项并保留元素的原始顺序。

var array = [1, 3, 2, 1, [5], 2, [4]]; // INPUT
var element = 0;
var decrement = array.length - 1;
while(element < array.length) {
  while(element < decrement) {
    if (array[element] === array[decrement]) {
      array.splice(decrement, 1);
      decrement--;
    } else {
      decrement--;
    }
  }
  decrement = array.length - 1;
  element++;
}
console.log(array);// [1, 3, 2, [5], [4]]
说明: Inner循环将数组的第一个元素与以最高索引处的元素开头的所有其他元素进行比较。向第一个元素递减,从数组中拼接出一个副本。 当内循环完成时,外循环递增到下一个元素进行比较并重置数组的新长度。

uharum

赞同来自:

如果您有任何机会使用

D3.js
你可以做到
d3.set(["foo", "bar", "foo", "baz"]).values() ==> ["foo", "bar", "baz"]
https://github.com/mbostock/d3/wiki/Arrays#set_values

wiusto

赞同来自:

Vanilla JS:使用像Set这样的Object删除重复项 你总是可以尝试将它放入一个对象,然后迭代它的键:

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"]

jenim

赞同来自:

for (i=0; i<basket.length; i++) {  
    if (!items.includes(basket[i]))
        items.push(basket[i]); 
}

xet

赞同来自:

在任何地方(甚至在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"]

ad_est

赞同来自:

“聪明”但天真的方式
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);
    });
}
这就是通常的做法。我们的想法是将每个元素放在一个哈希表中,然后立即检查它的存在。这给了我们线性时间,但至少有两个缺点:
  • 由于散列键只能是Javascript中的字符串,因此该代码不区分数字和“数字字符串”。也就是说,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);
    });
}

排序| uniq的 另一种选择是先对数组进行排序,然后删除与前一个元素相等的每个元素:
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) {
    var seen = new Set();
    return a.filter(item => {
        var k = key(item);
        return seen.has(k) ? false : seen.add(k);
    });
}
(有些人更喜欢!seen.has(k) && seen.add(k)而不是seen.has(k) ? false : seen.add(k))。

underscoreLo-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 ES6提供了Set对象,这使事情变得更加容易:
function uniq(a) {
   return Array.from(new Set(a));
}
要么
let uniq = a => [...new Set(a)];
请注意,与python不同,ES6集按插入顺序迭代,因此此代码保留原始数组的顺序。 但是,如果您需要具有唯一元素的数组,为什么不从一开始就使用集合?

taut

赞同来自:

以下内容比列出的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;
我的测试用例比较: http://jsperf.com/remove-duplicate-array-tests

ramet

赞同来自:

ES2015,1-liner,与map良好连接,但仅适用于整数:

[1, 4, 1].sort().filter((current, next) => current !== next)
[1, 4]

ksed

赞同来自:

您也可以使用JavaScript Lab library中的Array.unique()方法 - 或者从那里窃取想法。 但是,那里的代码编写得不是很好,因为它将unique()方法声明为Array原型的属性,因此将其添加到每个Array,打破了for...in功能(因为for...in循环将始终遍历unique变量,太)。

xsint

赞同来自:

aLinks是一个简单的JavaScript数组对象。如果在索引显示删除重复记录的元素之前存在任何元素。我重复取消所有重复项。一个通道阵列取消更多记录。

var srt_ = 0;
var pos_ = 0;
do {
    var srt_ = 0;
    for (var i in aLinks) {
        pos_ = aLinks.indexOf(aLinks[i].valueOf(), 0);
        if (pos_ < i) {
            delete aLinks[i];
            srt_++;
        }
    }
} while (srt_ != 0);

grem

赞同来自:

这可能是从阵列中永久删除重复项的最快方法之一 比这里的大多数功能快10倍。野生动物园快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)
}
  1. 测试:http://jsperf.com/wgu
  2. 演示:http://jsfiddle.net/46S7g/
  3. 更多:https://stackoverflow.com/a/25082874/2450730
如果你不能阅读上面的代码问,请阅读javascript书或这里有一些关于更短代码的解释。 https://stackoverflow.com/a/21353032/2450730

lsint

赞同来自:

我已经在其他一些问题上对dupe删除进行了详细的比较,但注意到这是我想在这里分享它的真实地方。 我相信这是最好的方法

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次,结果的平均值表明它们的性能不匹配。
  • 在firefox v47中减少& lut:14.85ms vs filter& indexOf:2836ms
  • 在chrome v51中减少& lut:23.90ms vs filter& indexOf:1066ms
好吧到目前为止一切都那么好。但是这次以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的数组,其数量范围<< ñ。我的意思是我们有一个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 :))

kex

赞同来自:

我知道我有点晚了,但这是使用jinqJs的另一个选项 See Fiddle

var result = jinqJs().from(["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"]).distinct().select();

yalias

赞同来自:

最简单的一个我到目前为止已经遇到过。在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

menim

赞同来自:

在不编写大量代码的情况下执行此操作的另一种方法是使用ES5 Object.keys方法:

var arrayWithDuplicates = ['a','b','c','d','a','c'],
    deduper = {};
arrayWithDuplicates.forEach(function (item) {
    deduper[item] = null;
});
var dedupedArray = Object.keys(deduper); // ["a", "b", "c", "d"]
在一个函数中提取
function removeDuplicates (arr) {
    var deduper = {}
    arr.forEach(function (item) {
        deduper[item] = null;
    });
    return Object.keys(deduper);
}

vvelit

赞同来自:

以下脚本返回仅包含唯一值的新数组。它适用于字符串和数字。不需要额外的库只有vanilla JS。 浏览器支持:

Feature Chrome  Firefox (Gecko)     Internet Explorer   Opera   Safari
Basic support   (Yes)   1.5 (1.8)   9                   (Yes)   (Yes)
https://jsfiddle.net/fzmcgcxv/3/
var duplicates = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl","Mike","Mike","Nancy","Carl"]; 
var unique = duplicates.filter(function(elem, pos) {
    return duplicates.indexOf(elem) == pos;
  }); 
alert(unique);

gomnis

赞同来自:

具有O(n)复杂度的Vanilla JS解决方案(此问题可能最快)。如果需要,修改hashFunction以区分对象(例如1和“1”)。第一种解决方案避免了隐藏的循环(在Array提供的函数中很常见)。

var dedupe = function(a) 
{
    var hash={},ret=[];
    var hashFunction = function(v) { return ""+v; };
    var collect = function(h)
    {
        if(hash.hasOwnProperty(hashFunction(h)) == false) // O(1)
        {
            hash[hashFunction(h)]=1;
            ret.push(h); // should be O(1) for Arrays
            return;
        }
    };
for(var i=0; i<a.length; i++) // this is a loop: O(n)
        collect(a[i]);
    //OR: a.forEach(collect); // this is a loop: O(n)
return ret;
}
var dedupe = function(a) 
{
    var hash={};
    var isdupe = function(h)
    {
        if(hash.hasOwnProperty(h) == false) // O(1)
        {
            hash[h]=1;
            return true;
        }
return false;
    };
return a.filter(isdupe); // this is a loop: O(n)
}

cut

赞同来自:

这只是另一种解决方案,但与其他方案不同。

function diffArray(arr1, arr2) {
  var newArr = arr1.concat(arr2);
  newArr.sort();
  var finalArr = [];
  for(var i = 0;i<newArr.length;i++) {
   if(!(newArr[i] === newArr[i+1] || newArr[i] === newArr[i-1])) {
     finalArr.push(newArr[i]);
   } 
  }
  return finalArr;
}

reum

赞同来自:

If using AngularJs then use filter like this
angular.module("myApp", []).controller("myController", function($scope) {
  $scope.targetArray = ['Apple', 'Apple', 'Banana', 'Mango', 'Strawberry', 'Banana'];
  $scope.filteredArray = [];
  $scope.removeDuplicates = function() {
    $scope.filteredArray = $scope.targetArray.filter(function(item, pos) {
      return $scope.targetArray.indexOf(item) == pos;
    });
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp">
<div ng-controller='myController'>
  <div>
    Actual Array: {{targetArray}} <br> Resulted Array: {{filteredArray}} <br>
    <button ng-click='removeDuplicates()'>Remove Duplicates</button>
  </div>
</body>

adolor

赞同来自:

厌倦了用for循环或jQuery看到所有不好的例子。 Javascript现在拥有完美的工具:排序,映射和缩小。

Uniq在保持现有订单的同时减少
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;},[]);

更快的uniq与排序 可能有更快的方法,但这个很不错。
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;},[]);

2015年更新:ES6版本: 在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)

oqui

赞同来自:

通用功能方法 以下是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) );
我们可以从unqiueBy轻松派生unique,或者使用Sets更快的实施:
const unqiue = uniqueBy(eq);
// const unique = xs => Array.from(new Set(xs));
这种方法的好处:
  • 使用单独的比较器功能的通用解决方案
  • 陈述性和简洁的实施
  • 重用其他小型通用函数

性能注意事项 uniqueBy没有使用循环的命令式实现那么快,但由于其通用性,它更具表现力。 如果您在应用中将uniqueBy识别为具体性能损失的原因,请将其替换为优化代码。也就是说,首先以功能性的声明方式编写代码。之后,如果遇到性能问题,请尝试优化位置的代码,这是导致问题的原因。

内存消耗和垃圾收集 uniqueBy利用隐藏在其体内的突变(push(x) (acc))。它重用累加器而不是在每次迭代后丢弃它。这减少了内存消耗和GC压力。由于这种副作用包含在函数内部,因此外部的所有内容都保持纯净。

yut

赞同来自:

const numbers = [1, 1, 2, 3, 4, 4];
function unique(array) {
  return array.reduce((a,b) => {
    let isIn = a.find(element => {
        return element === b;
    });
    if(!isIn){
      a.push(b);
    }
    return a;
  },[]);
}
let ret = unique(numbers); // [1, 2, 3, 4]
使用reduce和find的方式。

wab

赞同来自:

这里是没有任何特殊库的简单方法是特殊功能,

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)
enter image description here

asaepe

赞同来自:

var lines = ["Mike", "Matt", "Nancy", "Adam", "Jenny", "Nancy", "Carl"];
var uniqueNames = [];
for(var i=0;i<lines.length;i++)
{
    if(uniqueNames.indexOf(lines[i]) == -1)
        uniqueNames.push(lines[i]);
}
if(uniqueNames.indexOf(uniqueNames[uniqueNames.length-1])!= -1)
    uniqueNames.pop();
for(var i=0;i<uniqueNames.length;i++)
{
    document.write(uniqueNames[i]);
      document.write("<br/>");
}

eomnis

赞同来自:

在ECMAScript 6(又名ECMAScript 2015)中,Set可用于过滤掉重复项。然后可以使用spread operator将其转换回数组。

var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"],
    unique = [...new Set(names)];

sea

赞同来自:

删除字符串重复项的最简单方法是使用关联数组,然后遍历关联数组以使列表/数组返回。 如下所示:

var toHash = [];
var toList = [];
// add from ur data list to hash
$(data.pointsToList).each(function(index, Element) {
    toHash[Element.nameTo]= Element.nameTo;
});
// now convert hash to array
// don't forget the "hasownproperty" else u will get random results 
for (var key in toHash)  {
    if (toHash.hasOwnProperty(key)) { 
      toList.push(toHash[key]);
   }
}
瞧,现在重复了!

iaut

赞同来自:

使用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);
});

znihil

赞同来自:

所以选项是:

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]

hid

赞同来自:

最常见的答案具有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;
}

siusto

赞同来自:

https://jsfiddle.net/2w0k5tz8/

function remove_duplicates(array_){
    var ret_array = new Array();
    for (var a = array_.length - 1; a >= 0; a--) {
        for (var b = array_.length - 1; b >= 0; b--) {
            if(array_[a] == array_[b] && a != b){
                delete array_[b];
            }
        };
        if(array_[a] != undefined)
            ret_array.push(array_[a]);
    };
    return ret_array;
}
console.log(remove_duplicates(Array(1,1,1,2,2,2,3,3,3)));
循环,删除重复项,并创建克隆数组占位符,因为不会更新数组索引。 向后循环以获得更好的性能(您的循环不需要继续检查数组的长度)

oillo

赞同来自:

一条线:

let names = ['Mike','Matt','Nancy','Adam','Jenny','Nancy','Carl', 'Nancy'];
let dup = [...new Set(names)];
console.log(dup);

cvitae

赞同来自:

var duplicates = function(arr){
     var sorted = arr.sort();
   var dup = [];
   for(var i=0; i<sorted.length; i++){
        var rest  = sorted.slice(i+1); //slice the rest of array
       if(rest.indexOf(sorted[i]) > -1){//do indexOf
            if(dup.indexOf(sorted[i]) == -1)    
         dup.push(sorted[i]);//store it in another arr
      }
   }
   console.log(dup);
}
duplicates(["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"]);

asaepe

赞同来自:

一种简单但有效的技术是将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

yet

赞同来自:

去这个:

var uniqueArray = duplicateArray.filter(function(elem, pos) {
    return duplicateArray.indexOf(elem) == pos;
}); 
现在uniqueArray不包含重复项。

fharum

赞同来自:

这是一个简单的问题答案。

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]);
        }
    }

uut

赞同来自:

对于希望将具有重复元素的数组展平为一个唯一数组的任何人:

function flattenUniq(arrays) {
  var args = Array.prototype.slice.call(arguments);
var array = [].concat.apply([], args)
var result = array.reduce(function(prev, curr){
    if (prev.indexOf(curr) < 0) prev.push(curr);
    return prev;
  },[]);
return result;
}

non_et

赞同来自:

除了比当前的答案更简单,更简洁的解决方案(减去未来的ES6),我对此进行了测试,并且速度也快得多:

var uniqueArray = dupeArray.filter(function(item, i, self){
  return self.lastIndexOf(item) == i;
});
一个警告:在IE9中添加了Array.lastIndexOf(),所以如果你需要低于它,你需要寻找其他地方。

det

赞同来自:

$(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);
});

et_ea

赞同来自:

var uniqueCompnies = function(companyArray) {
    var arrayUniqueCompnies = [],
        found, x, y;
for (x = 0; x < companyArray.length; x++) {
        found = undefined;
        for (y = 0; y < arrayUniqueCompnies.length; y++) {
            if (companyArray[x] === arrayUniqueCompnies[y]) {
                found = true;
                break;
            }
        }
if ( ! found) {
            arrayUniqueCompnies.push(companyArray[x]);
        }
    }
return arrayUniqueCompnies;
}
var arr = [
    "Adobe Systems Incorporated",
    "IBX",
    "IBX",
    "BlackRock, Inc.",
    "BlackRock, Inc.",
];

veos

赞同来自:

尽管ES6解决方案是最好的,但我对于没有人展示以下解决方案感到困惑:

function removeDuplicates(arr){
    o={}
    arr.forEach(function(e){
        o[e]=true
    })
    return Object.keys(o)
}
这里要记住的是对象必须有唯一的键。我们正在利用它来删除所有重复项。我原本以为这将是最快的解决方案(在ES6之前)。 请记住,这也是对数组进行排序。

nvelit

赞同来自:

这是另一种使用jQuery的方法,

function uniqueArray(array){
  if ($.isArray(array)){
    var dupes = {}; var len, i;
    for (i=0,len=array.length;i<len;i++){
      var test = array[i].toString();
      if (dupes[test]) { array.splice(i,1); len--; i--; } else { dupes[test] = true; }
    }
  } 
  else {
    if (window.console) console.log('Not passing an array to uniqueArray, returning whatever you sent it - not filtered!');
      return(array);
  }
  return(array);
}
作者:威廉斯基莫尔

asaepe

赞同来自:

function arrayDuplicateRemove(arr){
    var c = 0;
    var tempArray = [];
    console.log(arr);
    arr.sort();
    console.log(arr);
    for (var i = arr.length - 1; i >= 0; i--) {
        if(arr[i] != tempArray[c-1]){
            tempArray.push(arr[i])
            c++;
        }
    };
    console.log(tempArray);
    tempArray.sort();
    console.log(tempArray);
}

rquis

赞同来自:

如果您自己创建阵列,则可以在插入数据时通过检查来保存循环和额外的唯一过滤器;

var values = [];
$.each(collection, function() {
    var x = $(this).value;
    if (!$.inArray(x, values)) {
        values.push(x);
    }
});

sit_et

赞同来自:

使用lodash快速轻松 - var array = ["12346","12347","12348","12349","12349"]; console.log(.uniqWith(array,.isEqual));

eomnis

赞同来自:

使用本机javascript函数从数组中删除重复项的最简洁方法是使用如下序列:

vals.sort().reduce(function(a, b){ if (b != a[0]) a.unshift(b); return a }, [])
在reduce函数中不需要sliceindexOf,就像我在其他示例中看到的那样!然而,将它与过滤器功能一起使用是有意义的:
vals.filter(function(v, i, a){ return i == a.indexOf(v) })
另一种已经在少数浏览器上运行的ES6(2015)方法是:
Array.from(new Set(vals))
甚至使用spread operator
[...new Set(vals)]
干杯!

zrerum

赞同来自:

function removeDuplicates (array) {
  var sorted = array.slice().sort()
  var result = []
sorted.forEach((item, index) => {
    if (sorted[index + 1] !== item) {
      result.push(item)
    }
  })
  return result
}

vanimi

赞同来自:

此解决方案使用新数组和函数内的对象映射。它所做的就是循环遍历原始数组,并将每个整数添加到对象map中。如果在循环遍历原始数组时,它会遇到重复,

`if (!unique[int])`
抓住这个,因为对象上已经有一个具有相同数字的关键属性。因此,跳过该数字并且不允许将其推入新数组中。
    function removeRepeats(ints) {
      var unique = {}
      var newInts = []
for (var i = 0; i < ints.length; i++) {
        var int = ints[i]
if (!unique[int]) {
          unique[int] = 1
          newInts.push(int)
        }
      }
      return newInts
    }
var example = [100, 100, 100, 100, 500]
    console.log(removeRepeats(example)) // prints [100, 500]

svero

赞同来自:

function removeDuplicates(inputArray) {
            var outputArray=new Array();
if(inputArray.length>0){
                jQuery.each(inputArray, function(index, value) {
                    if(jQuery.inArray(value, outputArray) == -1){
                        outputArray.push(value);
                    }
                });
            }           
            return outputArray;
        }

oalias

赞同来自:

如果您不想包含整个库,可以使用此一个来添加任何数组可以使用的方法:

Array.prototype.uniq = function uniq() {
  return this.reduce(function(accum, cur) { 
    if (accum.indexOf(cur) === -1) accum.push(cur); 
    return accum; 
  }, [] );
}
["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"].uniq()

bquia

赞同来自:

删除副本的最简单方法是执行for循环并比较不相同的元素并将它们推入新数组

 var array = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
var removeDublicate = function(arr){
 var result = []
 var sort_arr = arr.sort() //=> optional
 for (var i = 0; i < arr.length; i++) {
        if(arr[ i + 1] !== arr[i] ){
            result.push(arr[i])
        }
 };
  return result
}  
console.log(removeDublicate(array))
==>  ["Adam", "Carl", "Jenny", "Matt", "Mike", "Nancy"]

wab

赞同来自:

使用数组过滤器和indexOf函数的单行版本:

arr = arr.filter (function (value, index, array) { 
    return array.indexOf (value) == index;
});

ueaque

赞同来自:

使用Underscore.js 它是一个包含许多用于操作数组的函数的库。
It's the tie to go along with jQuery's tux, and Backbone.js's suspenders.
_.uniq
_.uniq(array, [isSorted], [iterator]) Alias: unique
Produces a duplicate-free version of the array, using === to test object equality. If you know in advance that the array is sorted, passing true for isSorted will run a much faster algorithm. If you want to compute unique items based on a transformation, pass an iterator function.
Example
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
alert(_.uniq(names, false));
注意:Lo-Dash(underscore竞争对手)也提供了类似的.uniq实施。

taut

赞同来自:

function removeDuplicates(myArray) {
  var uniqueElementArray = [];
  var len = myArray.length;
  if (len > 0) {
    uniqueElementArray.push(myArray[0]);
    var newArLen = 1;
    for (k = 1; k < len; k++) {
      var found = false;
      var newArLen = uniqueElementArray.length;
      for (m = 0; m < newArLen; m++) {
        if (myArray[k] == uniqueElementArray[m]) {
          found = true;
          break;
        }
      }
      if (!found) {
        uniqueElementArray.push(myArray[k]);
      }
    }
  }
  return uniqueElementArray;
}

dquia

赞同来自:

您可以使用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)

amagni

赞同来自:

略微修改了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);
    });
}