ramda.js - 在 R.pipe 中连续两次调用 R.reduce 之间累加器未重置

标签 ramda.js

考虑此代码,使用 Ramda 0.21.0:

var iteratee = (acc, [k, v]) => {
  acc[k] = ++v;
  return acc
}

var foo = R.pipe(
  R.toPairs,
  R.reduce(iteratee, {})
)

console.log(foo({ a: 1, b: 2})) // { a: 2, b: 3 }
console.log(foo({ c: 3, d: 4})) // { a: 2, b: 3, c: 4, d: 5 }

为什么第二次调用 foo 显示 { a: 2, b: 3, c: 4, d: 5 } 而不是 { c: 4、d:5}

是否正在进行某种内存?我希望每次应用 foo 时 acc 的初始值都会重置为 {}

最佳答案

这个答案主要扩展了 @iofjuupasli 的评论。

问题是累加器对象的突变。您在 foo 的定义中创建一个,它会在每次调用时重用,然后在 iteratee 中更新它(可怕的名字,恕我直言。称之为 bar 或其他东西。:-) )。有几种方法可以解决这个问题。一种可能是确保每次调用 foo 时都传递一个新的累加器:

var iteratee = (acc, [k, v]) => {
  acc[k] = ++v;
  return acc
}

var foo = R.pipe(
  R.toPairs,
  list => R.reduce(iteratee, {}, list)
)

foo({ a: 1, b: 2}); //=> {"a": 2, "b": 3}
foo({ c: 3, d: 4}); //=> {"c": 4, "d": 5}

这可行,但感觉不太令人满意。也许更有用的是避免在每次传递时改变累加器对象。 assoc将创建一个尽可能多地重用前一个对象的新对象:

var iteratee = (acc, [k, v]) => R.assoc(k, v + 1, acc)

var foo = R.pipe(
  R.toPairs,
  R.reduce(iteratee, {})
);

foo({ a: 1, b: 2}); //=> {"a": 2, "b": 3}
foo({ c: 3, d: 4}); //=> {"c": 4, "d": 5}

这看起来更干净。但实际上 Ramda 有一个更简单的解决方案。 map function 将对象视为要映射的仿函数。将此与 inc 结合起来,它只是增加一个值,我们可以这样做:

var foo = R.map(R.inc);

foo({ a: 1, b: 2}); //=> {"a": 2, "b": 3}
foo({ c: 3, d: 4}); //=> {"c": 4, "d": 5}

感觉真的很干净!

关于ramda.js - 在 R.pipe 中连续两次调用 R.reduce 之间累加器未重置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36650701/

相关文章:

javascript - 比较和转换多个数组

javascript - ramda.js - 如何将 fn 应用于集合的子集

javascript - 如何在 FP (Ramda.js) 中重写这个函数?

javascript - lambda js : lens for deeply nested objects with nested arrays of objects

javascript - 在 Ramda.js 中按属性过滤对象

javascript - lambda 。 anyPass 使用结果而不是 bool 值

javascript - 检查 Ticker 是否在另一个列表中,然后添加新键 [RamdaJS]

javascript - 组合 Ramda 函数

javascript - 使用函数式编程像 SQL 连接一样连接两个 JSON 对象数组

javascript - ramda.js 中是否有相当于 mapValues 的函数(类似于 lodash)?