javascript - 自定义迭代的功能方式

标签 javascript functional-programming

关闭。这个问题需要更多 focused .它目前不接受答案。












想改进这个问题?更新问题,使其仅关注一个问题 editing this post .

5年前关闭。




Improve this question




怎么才能只用map , reducefilter或在数组上创建自定义迭代的任何功能方式?

假设我想将一个数组映射到另一个数组,该数组保存源数组中每三个相邻元素的总和:

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.reduceArray.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/

相关文章:

javascript - 如何将 html 输入的值放入对象的 javascript 数组中

scala - 模式匹配如何在exists 函数中工作?

scala - 使用值与参数顺序不匹配的无形 HList 调用 Scala Function2

javascript - promise.then 是不是异步的?

javascript - 如何在 JS 中制作雪花飘落的动画?

javascript - 在我的 Cordova 项目中,我想在 iOS 键盘 'done' 按钮单击上触发一个功能(搜索功能)

javascript - 按属性对对象数组进行排序

javascript - 用JavaScript创建功能对象的优点/缺点是什么?

javascript - 写一个一元函数链接器,在 codewars 上出现 TypeError 但在 repl.it 上没有错误?

functional-programming - 用于函数式编程的 SOLID