簡體   English   中英

在多個數組中查找唯一值

[英]Finding unique values in multiple arrays

我正在嘗試解決具有此目標的freeCodeCamp 練習

編寫一個函數,該函數接受兩個或多個數組,並按照原始提供的數組的順序返回一個包含唯一值的新數組。

換句話說,所有數組中存在的所有值都應按其原始順序包含在內,但在最終數組中沒有重復項。

唯一數字應按其原始順序排序,但最終數組不應按數字順序排序。

所以我所做的是將所有參數連接到一個名為everything數組中。 然后我在數組中搜索重復項,然后搜索這些重復項的參數並將它們.splice()出來。

到目前為止,一切都按預期工作,但最后一個參數的最后一個數字沒有被刪除,我真的不知道為什么。

有人可以指出我做錯了什么嗎? 請記住,我正在努力學習,所以顯而易見的事情對我來說可能並不明顯,需要指出。 提前致謝。

 function unite(arr1, arr2, arr3) { var everything = []; //concat all arrays except the first one for(var x = 0; x < arguments.length; x++) { for(var y = 0; y < arguments[x].length; y++) { everything.push(arguments[x][y]); } } //function that returns duplicates function returnUnique(arr) { return arr.reduce(function(dupes, val, i) { if (arr.indexOf(val) !== i && dupes.indexOf(val) === -1) { dupes.push(val); } return dupes; }, []); } //return duplicates var dupes = returnUnique(everything); //remove duplicates from all arguments except the first one for(var n = 1; n < arguments.length; n++) { for(var m = 0; m < dupes.length; m++) { if(arguments[n].hasOwnProperty(dupes[m])) { arguments[n].splice(arguments[n].indexOf(dupes[m]), 1); } } } //return concatenation of the reduced arguments return arr1.concat(arr2).concat(arr3); } //this returns [1, 3, 2, 5, 4, 2] unite([1, 3, 2], [5, 2, 1, 4], [2, 1]);

看起來你有點過於復雜了;)

 function unite() { return [].concat.apply([], arguments).filter(function(elem, index, self) { return self.indexOf(elem) === index; }); } res = unite([1, 2, 3], [5, 2, 1, 4], [2, 1], [6, 7, 8]); document.write('<pre>'+JSON.stringify(res));

說明

我們把問題分成兩步:

  • 將參數組合成一個大數組
  • 從這個大數組中刪除非唯一元素

這部分處理第一步:

[].concat.apply([], arguments)

內置方法someArray.concat(array1, array2 etc)將給定的數組附加到目標。 例如,

[1,2,3].concat([4,5],[6],[7,8]) == [1,2,3,4,5,6,7,8]

如果我們的函數有固定參數,我們可以直接調用concat

function unite(array1, array2, array3) {
    var combined = [].concat(array1, array2, array3);
    // or
    var combined = array1.concat(array2, array3);

但由於我們不知道我們將收到多少參數,我們必須使用apply

 someFunction.apply(thisObject, [arg1, arg2, etc])

是相同的

 thisObject.someFunction(arg1, arg2, etc)

所以上面的行

 var combined = [].concat(array1, array2, array3);

可以寫成

 var combined = concat.apply([], [array1, array2, array3]);

或者干脆

 var combined = concat.apply([], arguments);

其中arguments是一個特殊的類數組對象,包含所有函數參數(實際參數)。

實際上,最后兩行是行不通的,因為concat不是一個普通的函數,它是Array對象的方法,因此是Array.prototype結構的成員。 我們必須告訴 JS 引擎在哪里可以找到concat 我們可以直接使用Array.prototype

 var combined = Array.prototype.concat.apply([], arguments);

或者創建一個新的、不相關的數組對象並從那里拉取concat

 var combined = [].concat.apply([], arguments);

這個原型方法稍微更有效(因為我們沒有創建一個虛擬對象),但也更冗長。

不管怎樣,第一步現在已經完成了。 為了消除重復,我們使用以下方法:

 combined.filter(function(elem, index) {
     return combined.indexOf(elem) === index;
 })

有關解釋和替代方案,請參閱此帖子

最后,我們去掉臨時變量( combined )並將“combine”和“dedupe”調用鏈在一起:

return [].concat.apply([], arguments).filter(function(elem, index, self) {
    return self.indexOf(elem) === index;
});

使用filter的第三個參數(“這個數組”),因為我們不再有變量了。

很簡單,不是嗎? ;) 如果您有任何問題,請告訴我們。

最后,如果您有興趣,可以做一個小練習:

combinededupe作為單獨的函數編寫。 創建一個函數compose ,它接受兩個函數ab並返回一個以相反順序運行這些函數的新函數,因此compose(a,b)(argument)將與b(a(argument)) unite = compose(combine, dedupe)替換上面的unite定義,並確保它的工作原理完全相同。

你也可以試試這個:

 var Data = [[1, 2, 3], [5, 2, 1, 4], [2, 1], [6, 7, 8]] var UniqueValues = [] for (var i = 0; i < Data.length; i++) { UniqueValues = [...new Set(UniqueValues.concat(Data[i]))] } console.log(UniqueValues)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM