考虑此代码,使用 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/