组合两个大小相同的数组并返回sum
Combining two arrays of same size and returns sum
在Javascript(或任何其他具有类似函数语法的编程语言)中,如果我有两个相同大小的数组,例如a = [1,2,3,4]
和b=[5,6,7,8]
,得到以下结果的最有效方法是什么?c=[6,8,10,12]
.
现在,我做:
a.map(function(x,i){
return x+b[i]
})
,但理想情况下,我想要一个不涉及使用索引的解决方案
ES5数组方法很棒,但是旧的for
循环更快。
var sum = Array(a.length);
for(var i=0; i<a.length; ++i)
sum[i] = a[i] + b[i];
警告: @dangor的答案改变了其中一个输入,这在我看来非常糟糕。我的答案会给你你的结果,没有副作用。
Babel demo —下面的代码是使用ES6编写的。如果你想要ES5代码,查看Babel REPL的右边面板。
我建议首先使用zip
函数。这个函数将接受两个数组,并创建一个元组数组。
// zip :: [a] -> [b] -> [(a,b)]
let zip = (xs, ys) => {
let iter = (zs, [x, ...xs], [y, ...ys]) =>
(!x || !y) ? zs : iter(zs.concat([[x,y]]), xs, ys)
return iter([], xs, ys);
};
let a = [1,2,3,4];
let b = [5,6,7,8];
zip(a,b); //=> [[1,5], [2,6], [3,7], [4,8]]
现在可以在每个元组
上使用map
zip(a,b).map(t => t[0] + t[1]);
//=> [6,8,10,12]
最后一段看起来有点脏,但是如果我们继续构建一些更实用的构建块,我们可以把它清理干净
如果我们注意到,在映射函数中,我们所做的只是对数组的元素求和。我们可以通过创建这样的函数来避免过于具体。
让我们先看看如何对数组求和…
[1,2,3,4].reduce((x, y) => x + y, 0); //=> 10
好的,首先我们要改进的是闭包。该函数是一个简单的add
函数。
let add = (x,y) => x + y;
[1,2,3,4].reduce(add, 0); //=> 10
但是我们如何使用它来改进我们的原始代码呢?
// original code
zip(a,b).map(t => t[0] + t[1]); //=> [6,8,10,12]
// improvement #1
zip(a,b).map(t => t.reduce(add, 0)); //=> [6,8,10,12]
好的,还没有很大的改进,而且在我们修复reduce
函数之前,它不会变得更好。JavaScript强迫我们使用这种表示法来调用reduce: obj.reduce(fn, i)
。这个参数顺序有点糟糕,所以让我们修正
// improvement #2
let reduce = f => i => xs => xs.reduce(f, i);
zip(a,b).map(reduce(add)(0)); //=> [6,8,10,12]
最后,我们可以定义一个sum
函数
reduce(add)(0)
。// improvement #3
let sum = reduce(add)(0);
zip(a,b).map(sum); //=> [6,8,10,12]
let zip = (xs, ys) => {
let iter = (zs, [x, ...xs], [y, ...ys]) =>
(!x || !y) ? zs : iter(zs.concat([[x,y]]), xs, ys)
return iter([], xs, ys);
};
let add = (x,y) => x + y;
let reduce = f => i => xs => xs.reduce(f, i);
let sum = reduce(add)(0);
let a = [1,2,3,4];
let b = [5,6,7,8];
let result = zip(a,b).map(sum);
console.log(result);
//=> [6,8,10,12]
当然,这会导致比其他解决方案更全面的代码,但是练习的重点是,当您使用此方法到达解决方案时,您有四个函数,现在您可以将其重新用于其他代码:
zip
, add
, reduce
和sum
都非常通用;所有这些都是总数和纯洁。最后,这些函数的使用为我们提供了一个无点的解决方案,它展示了比命令式更强大的声明性方言。
我希望这能帮助你了解如何组合几个较小的函数来实现你的目标—所有的,而不需要做一些愚蠢的事情,比如求助于强制的for
循环或屈服于鲁莽的副作用,比如改变输入。
还有一个更短的选择,使用Array.map():
a = [1,2,3,4];
b = [5,6,7,8];
var result = a.map(function(item){
return item + b.shift();
})
没有索引?我不知道这是否比您的原始代码更有效,但是您可以对ecodeparadox的答案进行一些改进,它已经假设您不需要保留原始数组。
- 使用pop代替shift(后面跟着最后的反转)
- 使用循环代替递归
类似:
function doSum(a, b) {
var sum = [];
while (a.length) sum.push(a.pop() + b.pop());
return sum.reverse();
}
- 如何在映射数组中添加换行符
- javascript结合了数组和字典
- 需要帮助设置json数组
- 不能从angular2中的子组件指定父组件中的数组
- 使用JS将数组转换为json对象
- 数组在递归方法中设置为null
- knockoutjs可观察数组
- Javascript-如何读取json文件中的列并将其保存在Javascript数组中
- 将数组从PHP传递到Javascript
- JavaScript数组排序(函数)用于对表行进行排序,而不是排序
- 在函数中添加数组元素的数值
- 无法通过数组映射绑定
- javascript中的数组出错
- 从输入数组中获取sum's元素
- parseInt关于数组和sum问题
- 数组中单词的匹配(sum)、(min)的正则表达式
- 调用reduce to sum对象数组返回NaN
- 组合两个大小相同的数组并返回sum
- 添加了Javascript数组sum min Max
- Sum数组push值,在0 javascript之前