如何获得数组中的唯一值

我怎样才能得到一个数组中的唯一值列表? 我是否总是要使用第二个数组,或者在JavaScript中有类似于java的hashmap的东西吗?

我将只使用JavaScriptjQuery 。 没有额外的库可以使用。

因为我在@ Rocket的回答中继续讨论这个问题,所以我不妨提供一个不使用库的例子。 这需要两个新的原型function, containsunique

 Array.prototype.contains = function(v) { for(var i = 0; i < this.length; i++) { if(this[i] === v) return true; } return false; }; Array.prototype.unique = function() { var arr = []; for(var i = 0; i < this.length; i++) { if(!arr.includes(this[i])) { arr.push(this[i]); } } return arr; } 

你可以这样做:

 var duplicates = [1,3,4,2,1,2,3,8]; var uniques = duplicates.unique(); // result = [1,3,4,2,8] 

为了获得更高的可靠性,可以用MDN的indexOf shimreplacecontains ,并检查每个元素的indexOf是否等于-1: https : //developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf

或者对于那些正在寻找一个单行(简单和function), 与目前的浏览器兼容的人来说

 var a = ["1", "1", "2", "3", "3", "1"]; var unique = a.filter(function(item, i, ar){ return ar.indexOf(item) === i; }); 

更新18-04-17

看起来好像“Array.prototype.includes”现在在主线浏览器的最新版本中具有广泛的支持( 兼容性 )

更新29/07/2015:

在浏览器中有计划支持一个标准化的“Array.prototype.includes”方法,虽然这个方法并没有直接回答这个问题, 往往是相关的。

用法:

 ["1", "1", "2", "3", "3", "1"].includes("2"); // true 

Pollyfill( 浏览器支持 , 来自mozilla ):

 // https://tc39.github.io/ecma262/#sec-array.prototype.includes if (!Array.prototype.includes) { Object.defineProperty(Array.prototype, 'includes', { value: function(searchElement, fromIndex) { // 1. Let O be ? ToObject(this value). if (this == null) { throw new TypeError('"this" is null or not defined'); } var o = Object(this); // 2. Let len be ? ToLength(? Get(O, "length")). var len = o.length >>> 0; // 3. If len is 0, return false. if (len === 0) { return false; } // 4. Let n be ? ToInteger(fromIndex). // (If fromIndex is undefined, this step produces the value 0.) var n = fromIndex | 0; // 5. If n ≥ 0, then // a. Let k be n. // 6. Else n < 0, // a. Let k be len + n. // b. If k < 0, let k be 0. var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0); // 7. Repeat, while k < len while (k < len) { // a. Let elementK be the result of ? Get(O, ! ToString(k)). // b. If SameValueZero(searchElement, elementK) is true, return true. // c. Increase k by 1. // NOTE: === provides the correct "SameValueZero" comparison needed here. if (o[k] === searchElement) { return true; } k++; } // 8. Return false return false; } }); } 

一个class轮,纯粹的JavaScript

使用ES6语法

list = list.filter((x, i, a) => a.indexOf(x) == i)

 x --> item in array i --> index of item a --> array reference, (in this case "list") 

在这里输入图像说明

使用ES5语法

 list = list.filter(function (x, i, a) { return a.indexOf(x) == i; }); 

浏览器兼容性 :IE9 +

如果你想保留原始数组,

你需要第二个数组来包含first-

大多数浏览器都有Array.prototype.filter

 var unique= array1.filter(function(itm, i){ return array1.indexOf(itm)== i; // returns true for only the first instance of itm }); //if you need a 'shim': Array.prototype.filter= Array.prototype.filter || function(fun, scope){ var T= this, A= [], i= 0, itm, L= T.length; if(typeof fun== 'function'){ while(i<L){ if(i in T){ itm= T[i]; if(fun.call(scope, itm, i, T)) A[A.length]= itm; } ++i; } } return A; } Array.prototype.indexOf= Array.prototype.indexOf || function(what, i){ if(!i || typeof i!= 'number') i= 0; var L= this.length; while(i<L){ if(this[i]=== what) return i; ++i; } return -1; } 

这里有一个更清洁的ES6解决scheme,我看不包括在这里。 它使用Set和spread运算符 : ...

 var a = [1, 1, 2]; [... new Set(a)] 

其中返回[1, 2]

使用第二个数组的短而甜的解决scheme

 var axes2=[1,4,5,2,3,1,2,3,4,5,1,3,4]; var distinct_axes2=[]; for(var i=0;i<axes2.length;i++) { var str=axes2[i]; if(distinct_axes2.indexOf(str)==-1) { distinct_axes2.push(str); } } console.log("distinct_axes2 : "+distinct_axes2); // distinct_axes2 : 1,4,5,2,3 

现在,您可以使用ES6的Set数据types将您的数组转换为唯一的Set。 然后,如果你需要使用数组方法,你可以把它变成一个数组:

 var arr = ["a", "a", "b"]; var uniqueSet = new Set(arr); // {"a", "b"} var uniqueArr = Array.from(uniqueSet); // ["a", "b"] //Then continue to use array methods: uniqueArr.join(", "); // "a, b" 

使用jQuery,这是我做的一个数组独特的function:

 Array.prototype.unique = function () { var arr = this; return $.grep(arr, function (v, i) { return $.inArray(v, arr) === i; }); } console.log([1,2,3,1,2,3].unique()); // [1,2,3] 

你只需要香草JS来find独一无二的Array.some和Array.reduce。 ES2015语法只有62个字符。

 a.reduce((c, v) => b.some(w => w === v) ? c : c.concat(v)), b) 

在IE9 +和其他浏览器中支持Array.some和Array.reduce。 只需将常规function的胖箭头function更改为支持不支持ES2015语法的浏览器。

 var a = [1,2,3]; var b = [4,5,6]; // .reduce can return a subset or superset var uniques = a.reduce(function(c, v){ // .some stops on the first time the function returns true return (b.some(function(w){ return w === v; }) ? // if there's a match, return the array "c" c : // if there's no match, then add to the end and return the entire array c.concat(v)}), // the second param in .reduce is the starting variable. This is will be "c" the first time it runs. b); 

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects /arrays/缩小

在Javascript中不是原生的,但有很多库有这种方法。

_.uniq(array)_.uniq(array) ( 链接 )工作得很好( 源 )。

上述多数解决scheme运行时间复杂度高。

这里是使用reduce的解决scheme,并且可以在O(n)时间内完成这项工作

 Array.prototype.unique = Array.prototype.unique || function() { var arr = []; this.reduce(function (hash, num) { if(typeof hash[num] === 'undefined') { hash[num] = 1; arr.push(num); } return hash; }, {}); return arr; } var myArr = [3,1,2,3,3,3]; console.log(myArr.unique()); //[3,1,2]; 

目前解决scheme唯一的问题是效率。 如果你担心这一点(你可能应该),你需要避免嵌套循环:为*,筛选* indexOf,grep * inArray,他们都迭代数组多次。 你可以用这样或者这样的解决scheme实现一个单一的循环

这个问题的另一个想法。 这是我做了什么,用更less的代码来实现这一点。

 var distinctMap = {}; var testArray = ['John', 'John', 'Jason', 'Jason']; for (var i = 0; i < testArray.length; i++) { var value = testArray[i]; distinctMap[value] = ''; }; var unique_values = Object.keys(distinctMap); 
 Array.prototype.unique = function () { var dictionary = {}; var uniqueValues = []; for (var i = 0; i < this.length; i++) { if (dictionary[this[i]] == undefined){ dictionary[this[i]] = i; uniqueValues.push(this[i]); } } return uniqueValues; } 
 function findUnique(arr) { var result = []; arr.forEach(function (d) { if (result.indexOf(d) === -1) result.push(d); }); return result; } var unique = findUnique([1, 2, 3, 1, 2, 1, 4]); // [1,2,3,4] 

ES6方式:

 const uniq = (arr) => (arr.filter((item, index, arry) => (arry.indexOf(item) === index))); 

我已经在纯JS中试过这个问题。 我遵循以下步骤1.对给定的数组进行sorting,2.遍历sorting后的数组,3.使用当前值validation上一个值和下一个值

 // JS var inpArr = [1, 5, 5, 4, 3, 3, 2, 2, 2,2, 100, 100, -1]; //sort the given array inpArr.sort(function(a, b){ return ab; }); var finalArr = []; //loop through the inpArr for(var i=0; i<inpArr.length; i++){ //check previous and next value if(inpArr[i-1]!=inpArr[i] && inpArr[i] != inpArr[i+1]){ finalArr.push(inpArr[i]); } } console.log(finalArr); 

演示

我只是想,如果我们可以使用线性search来消除重复:

 JavaScript: function getUniqueRadios() { var x=document.getElementById("QnA"); var ansArray = new Array(); var prev; for (var i=0;i<x.length;i++) { // Check for unique radio button group if (x.elements[i].type == "radio") { // For the first element prev will be null, hence push it into array and set the prev var. if (prev == null) { prev = x.elements[i].name; ansArray.push(x.elements[i].name); } else { // We will only push the next radio element if its not identical to previous. if (prev != x.elements[i].name) { prev = x.elements[i].name; ansArray.push(x.elements[i].name); } } } } alert(ansArray); 

}

HTML:

 <body> <form name="QnA" action="" method='post' "> <input type="radio" name="g1" value="ANSTYPE1"> good </input> <input type="radio" name="g1" value="ANSTYPE2"> avg </input> <input type="radio" name="g2" value="ANSTYPE3"> Type1 </input> <input type="radio" name="g2" value="ANSTYPE2"> Type2 </input> <input type="submit" value='SUBMIT' onClick="javascript:getUniqueRadios()"></input> </form> </body> 

这里是解决问题的单线解决scheme:

 var seriesValues = [120, 120, 120, 120]; seriesValues = seriesValues.filter((value, index, seriesValues) => (seriesValues.slice(0, index)).indexOf(value) === -1); console.log(seriesValues); 

我有内置的JQuery独特的function。

 uniqueValues= jQuery.unique( duplicateValues ); 

更多的你可以参考jQuery API文档。

http://api.jquery.com/jquery.unique/