Mih*_*šič 1 javascript arrays for-loop
我正在尝试解决具有以下目标的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]);Run Code Online (Sandbox Code Playgroud)
看起来您有点复杂了;)
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));Run Code Online (Sandbox Code Playgroud)
我们将问题分为两个步骤:
此部分处理第一步:
[].concat.apply([], arguments)
Run Code Online (Sandbox Code Playgroud)
内置方法someArray.concat(array1, array2 etc)将给定数组附加到目标。例如,
[1,2,3].concat([4,5],[6],[7,8]) == [1,2,3,4,5,6,7,8]
Run Code Online (Sandbox Code Playgroud)
如果我们的函数具有固定的参数,则可以concat直接调用:
function unite(array1, array2, array3) {
var combined = [].concat(array1, array2, array3);
// or
var combined = array1.concat(array2, array3);
Run Code Online (Sandbox Code Playgroud)
但由于我们不知道要接收多少个args,因此必须使用apply。
someFunction.apply(thisObject, [arg1, arg2, etc])
Run Code Online (Sandbox Code Playgroud)
是相同的
thisObject.someFunction(arg1, arg2, etc)
Run Code Online (Sandbox Code Playgroud)
所以上面的线
var combined = [].concat(array1, array2, array3);
Run Code Online (Sandbox Code Playgroud)
可以写成
var combined = concat.apply([], [array1, array2, array3]);
Run Code Online (Sandbox Code Playgroud)
或简单地
var combined = concat.apply([], arguments);
Run Code Online (Sandbox Code Playgroud)
其中arguments是一个特殊的类似数组的对象,其中包含所有函数参数(实际参数)。
实际上,最后两行不起作用,因为concat它不是简单的函数,而是Array对象的方法,因此也是Array.prototype结构的成员。我们必须告诉JS引擎在哪里可以找到concat。我们可以Array.prototype直接使用:
var combined = Array.prototype.concat.apply([], arguments);
Run Code Online (Sandbox Code Playgroud)
或创建一个新的,不相关的数组对象并concat从此处拉出:
var combined = [].concat.apply([], arguments);
Run Code Online (Sandbox Code Playgroud)
这种原型方法效率稍高(因为我们没有创建虚拟对象),但是也比较冗长。
无论如何,第一步已经完成。为了消除重复,我们使用以下方法:
combined.filter(function(elem, index) {
return combined.indexOf(elem) === index;
})
Run Code Online (Sandbox Code Playgroud)
有关说明和替代方法,请参阅此文章。
最后,我们摆脱了临时变量(combined),并将“ combine”和“ dedupe”调用链链接在一起:
return [].concat.apply([], arguments).filter(function(elem, index, self) {
return self.indexOf(elem) === index;
});
Run Code Online (Sandbox Code Playgroud)
使用的第三个参数(“此数组”)是filter因为我们没有变量了。
很简单,不是吗?;)让我们知道您是否有任何疑问。
最后,如果您有兴趣,可以做一个小练习:
编写
combine和dedupe作为单独的函数。创建一个compose具有两个函数a并b返回一个新函数的函数,该新函数以相反的顺序运行这些函数,因此compose(a,b)(argument)与相同b(a(argument))。替换的上述定义unite用unite = compose(combine, dedupe),并确保它的工作原理完全一样。
| 归档时间: |
|
| 查看次数: |
795 次 |
| 最近记录: |