2012-06-28 37 views
86

如何獲取數組中唯一值的列表?我是否總是需要使用第二個數組,或者在JavaScript中有類似於java的hashmap的東西嗎?如何獲取數組中的唯一值

我打算使用JavaScriptjQuery只。沒有額外的庫可以使用。

+2

http://stackoverflow.com/questions/5381621/jquery-function-to-get-all-unique-elements-from-an-array - 準確地描述你想要什麼我認爲? – SpaceBison

+1

你打算使用'underscore.js'庫嗎? – jakee

+0

一個java hashmap與一個javascript對象基本相同。語法是{「key」:「value」,「key2」:「value2」} – Ian

回答

80

因爲我在@ Rocket的回答中繼續討論它,所以我不妨提供一個不使用庫的例子。這需要兩個新的原型功能,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墊片更換contains,檢查每個元素的indexOf等於-1:https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf

+0

謝謝你的例子。我會用它們過濾選擇框的選項。這應該很好。 – Astronaut

+0

'〜a.indexOf(b)===(a.indexOf(b)== -1)' – Orwellophile

+0

@Orwellophile我對你的回答更加明確,主要是對像我這樣的初學者用戶。你能解釋一下如何使用它嗎? –

2

在JavaScript中不是本地的,但大量的圖書館有這種方法。

Underscore.js的_.uniq(array)link)工作得很好(source)。

+0

感謝分享!該函數將迭代器和上下文與數組一起作爲v1.4.3的參數列表。 – KunJ

4

使用jQuery,這裏是一個數組獨特的功能,我提出:

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] 
+3

如果您打算在覈心JavaScript對象的原型中使用jQuery,編寫一個jQuery函數(比如'$ .uniqueArray(arr)')可能會更好嗎?在'Array'的原型中嵌入對jQuery的引用似乎值得懷疑 – jackwanders

+1

@jackwanders:有什麼值得質疑的呢?如果你在頁面上有jQuery,我們來使用它。 –

+0

只是你寫的新的獨特函數現在依賴於jQuery;如果沒有確保jQuery在那裏使用,您不能將其移動到新的站點或應用程序。 – jackwanders

13

如果你要離開原來的陣列完好,

你需要第二個數組包含一線的潮頭元素

大多數瀏覽器都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; 
    } 
+0

@ Rocket-謝謝! – kennebec

-1

我只是想如果我們可以使用線性搜索來消除重複項:

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> 
0

唯一的問題迄今給出的解決方案是效率。如果你擔心這一點(你可能應該),你需要避免嵌套循環:對於* for,filter * indexOf,grep * inArray,它們都會多次迭代數組。您可以實現與像thisthis

128

或者爲那些尋找一個班輪(簡單功能),兼容解決方案的單迴路與當前瀏覽器

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。包括如今在主線瀏覽器(compatibility)的最新版本

更新29/07/2015廣泛支持:

有在工程計劃的瀏覽器支持標準的「Array.prototype包括'方法,雖然不直接回答這個問題;往往是相關的。

用法:

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

Pollyfill(browser supportsource from 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; 
    } 
    }); 
} 
+1

感謝您的,相當優雅 – felipekm

+0

這幾乎是來自kennebec的複製粘貼,但承認傳遞數組作爲參數而不是使用閉包可能會提高性能。 – nus

+0

- 必須說我沒有連接點,只是掃描一個單一的班輪,看起來像一個大的職位,所以跳過了,去找到一個替代來源,並重新張貼給其他人找到快速。這就是說,你的權利;幾乎和肯尼貝克一樣。 –

-2

我有內置JQuery的獨特功能。

uniqueValues= jQuery.unique(duplicateValues); 

欲瞭解更多,你可以參考jQuery API文檔。

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

+7

_請注意,這隻適用於DOM元素數組,而不是字符串或數字。 – mco

5

短和甜溶液使用第二陣列;

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 
+0

短?甜美?你看過頂級解決方案嗎? –

3

你只需要香草JS來找到與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。只需將常規功能的胖箭頭功能更改爲支持不支持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/Array/Reduce

0

這個問題的另一種思考。這是我用少量代碼實現的。

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

這些天來,你可以使用ES6的集合數據類型的數組轉換爲一組唯一的。然後,如果你需要使用陣列的方法,你可以把它放回一個數組:

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" 
+0

整潔,會很高興看到一些perfomance數字,我認爲轉換themsets特別是如果他們是非常動態和大可能是一個性能heickup,只能告訴的方式是測試:) – Astronaut

+0

很光滑,遺憾的是仍然不支持IE11 ... – Hank

+0

如果您使用的是轉譯器或處於支持它的環境中,則可以更簡潔地做同樣的事情:var uniqueArr = [... new Set(arr)]; // [「a」,「b」]' – Stenerson

-1

這裏是一個班輪解決問題的辦法:

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

複製粘貼到瀏覽器控制檯並得到結果,喲:-)

0

ES6 way:

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

一個襯裏,純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") 

enter image description here

隨着ES5語法

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

瀏覽器兼容性:IE9 +

+2

不知道爲什麼這是被拒絕。它可能一開始並不明顯,並且可能被分類爲「聰明」而不實用,但是它是陳述性的,非破壞性的,簡潔的,其中大部分其他答案都是缺乏的。 – Larry

+0

@Larry這是倒票,因爲完全相同的答案是在這一年前提供的。 –

+0

@AlexOkrushko足夠公平 - 因爲格式化而錯過了答案 – Larry

27

下面是ES6,我看到這裏不包括更清潔的解決方案。它使用Setspread operator...

var a = [1, 1, 2]; 

[... new Set(a)] 

它返回[1, 2]

+1

這太聰明瞭! –

+1

現在,**這是**一行! – Mac

0

我已經在純JS試過這個問題。 我按照以下步驟1排序的給定的陣列中,2.遍歷排序後的數組,3.驗證先前值和下一值與電流值

// 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 a-b; 
}); 

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

Demo

3

多數以上已經解的運行時間複雜度高。

以下是使用reduce的解決方案,並且可以在O(n)時間完成的工作。

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

注:

該解決方案不依賴於降低。這個想法是創建一個對象映射並將唯一的映射推送到數組中。

0

快速,緊湊,沒有嵌套循環,可以與任何對象一起使用,不僅僅是字符串和數字,只需要一個謂詞,並且只有5行代碼!

function findUnique(arr, predicate) { 
    var found = {}; 
    arr.forEach(d => { 
    found[predicate(d)] = d; 
    }); 
    return Object.keys(found).map(key => found[key]); 
} 

例:按類型找到獨特的物品:

var things = [ 
    { name: 'charm', type: 'quark'}, 
    { name: 'strange', type: 'quark'}, 
    { name: 'proton', type: 'boson'}, 
]; 

var result = findUnique(things, d => d.type); 
// [ 
// { name: 'charm', type: 'quark'}, 
// { name: 'proton', type: 'boson'} 
// ] 

如果你想要找到的不是上次加found.hasOwnPropery第一唯一項目()在那裏檢查。

0
function findUniques(arr){ 
    let uniques = [] 
    arr.forEach(n => { 
    if(!uniques.includes(n)){ 
     uniques.push(n) 
    }  
    }) 
    return uniques 
} 

let arr = ["3", "3", "4", "4", "4", "5", "7", "9", "b", "d", "e", "f", "h", "q", "r", "t", "t"] 

findUniques(arr) 
// ["3", "4", "5", "7", "9", "b", "d", "e", "f", "h", "q", "r", "t"]