繁体   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