关闭。这个问题需要更多 focused .它目前不接受答案。
想改进这个问题?更新问题,使其仅关注一个问题 editing this post .
5年前关闭。
Improve this question
怎么才能只用map
, reduce
或 filter
或在数组上创建自定义迭代的任何功能方式?
假设我想将一个数组映射到另一个数组,该数组保存源数组中每三个相邻元素的总和:
var source = [1, 2, 3, 4, 6, 7, 8] // to [6, 17, 8]
或者制作一个包含两个元素的桶:
var source = [1, 2, 3, 4, 5, 6, 7] // to [[1, 2], [3, 4], [5, 6], [7]]
对于第二个,我有以下内容,但是当我按索引访问数组时,这看起来不是很实用:
function* pairMap(data) {
yield* data.map((item, index) => {
if (index > 0) {
return [data[index - 1], item];
}
});
}
我对这样做的功能方式很感兴趣。
最佳答案
Let's say I wanna map an array to another array which holds the sum of each three adjacent elements in the source array:
var source = [1, 2, 3, 4, 6, 7, 8] // to [6, 17, 8]
map 创建 1:1 关系,因此这不适合使用
map
.相反,reduce
or ("fold") 在这里会更好。const comp = f=> g=> x=> f (g (x));
const len = xs=> xs.length;
const isEmpty = xs=> len(xs) === 0;
const concat = xs=> ys=> ys.concat(xs);
const chunk= n=> xs=>
isEmpty (xs)
? []
: concat (chunk (n) (xs.slice(n))) ([xs.slice(0,n)]);
const reduce = f=> y=> xs=> xs.reduce((y,x)=> f(y)(x), y);
const map = f=> xs=> xs.map(x=> f(x));
const add = x=> y=> y + x;
const sum = reduce (add) (0);
var source = [1, 2, 3, 4, 6, 7, 8];
comp (map (sum)) (chunk (3)) (source);
//=> [ 6, 17, 8 ]
如您所见,我们首先转换
source
分成 3 block ,然后我们 map
sum
作用于每个 block 。当您听到人们谈论“声明性”代码时,最后一行非常清楚,并且很少担心实现。我们不是在告诉计算机如何完成它的工作。没有
for
/while
循环,没有多余的变量或迭代器,没有逻辑等。“idgaf 如何,只需将
source
分成 3 组,然后对每个部分求和”// very declaration, wow
comp (map (sum)) (chunk (3)) (source);
Or make a bucket of two elements:
var source = [1, 2, 3, 4, 5, 6, 7] // to [[1, 2], [3, 4], [5, 6], [7]]
使用上面相同的代码
var source = [1, 2, 3, 4, 5, 6, 7];
chunk (2) (source);
// => [ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ], [ 7 ] ]
For the second one I have the following but that doesn't look very functional as I'm accessing array by index:
function* pairMap(data) { yield* data.map((item, index) => { if (index > 0) { return [data[index - 1], item]; } }); }
使用上面的代码,你可以实现
pairMap
容易地const pairMap = f=> comp (map (f)) (chunk (2));
var source = [1, 2, 3, 4, 5, 6, 7];
pairMap (pair => console.log(pair)) (source);
// [ 1, 2 ]
// [ 3, 4 ]
// [ 5, 6 ]
// [ 7 ]
学习所有的东西
问题是“自定义迭代的功能方式”。你会注意到我的代码有点作弊,使用
Array.prototype.reduce
和 Array.prototype.map
.学习如何自己构建这些是一个很好的学习工具,让我了解构建功能循环/迭代器/控件既有趣又简单const isEmpty = xs=> xs.length === 0
const head = xs=> xs[0];
const tail = xs=> xs.slice(1);
const reduce = f=> y=> xs=>
isEmpty (xs)
? y
: reduce (f) (f (y) (head (xs))) (tail (xs));
const add = x=> y=> y + x;
reduce (add) (0) ([1,2,3]);
//=> 6
有用!。
好的,让我们看看我们如何做 map
const concat = xs=> ys=> ys.concat(xs);
const append = x=> concat ([x]);
const map = f=>
reduce (ys=> x=> append (f (x)) (ys)) ([]);
const sq = x => x * x;
map (sq) ([1,2,3])
//=> [ 1, 4, 9 ]
测验 1:可以写
filter
, some
, 和 every
使用 reduce
?巨魔警告:有许多不同的方式来实现这些功能。如果您开始编写递归函数,您首先要了解的是 tail call是。 ES6 正在优化尾调用,但暂时不会普及。有一段时间,Babel 可以使用 while 循环转换它,但它在版本 6 中暂时禁用,一旦修复它就会回来。
测验 2:你怎么能重写我的
reduce
有适当的尾声?
关于javascript - 自定义迭代的功能方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37263095/