[英]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
的第三個參數(“這個數組”),因為我們不再有變量了。
很簡單,不是嗎? ;) 如果您有任何問題,請告訴我們。
最后,如果您有興趣,可以做一個小練習:
將
combine
和dedupe
作為單獨的函數編寫。 創建一個函數compose
,它接受兩個函數a
和b
並返回一個以相反順序運行這些函數的新函數,因此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.