如果使用 Ramda reduce 但使用 native 则 Jest 测试失败
Jest test fails if using Ramda reduce but passes with native
我注意到,如果我使用 ramda
,有时我会在尝试为我正在导出的方法编写 Jest
测试时遇到问题。我已经将问题归结为以下测试和两个基本的减速器功能。我已将它们张贴在 gist
上,以免代码堵塞这个问题。
https://gist.github.com/beardedtim/99aabe3b08ba58037b20d65343ed9d20
我在使用 ramda
reducer 时遇到以下错误:
● counter usage › counter counts the words and their index in the given list of words
expect(received).toEqual(expected)
Expected value to equal:
[{"count": 3, "indexes": [0, 2, 4], "value": "a"}, {"count": 1, "indexes": [1], "value": "b"}, {"count": 1, "indexes": [3], "value": "c"}]
Received:
[{"count": 15, "indexes": [0, 2, 4, 0, 2, 4, 0, 2, 4, 0, 2, 4, 0, 2, 4], "value": "a"}, {"count": 5, "indexes": [1, 1, 1, 1, 1], "value": "b"}, {"count": 5, "indexes": [3, 3, 3, 3, 3
], "value": "c"}]
这让我相信 ramda
的 reduce 是保持某种状态或彼此共享 words
。我不确定这是怎么回事。任何人都知道我应该用谷歌搜索什么或者其他 docs/examples 处理这个的人?
状态数组 (final
) 硬连接到 reduceWithIndex
。对此函数的所有调用共享同一个 final
数组。
试试这个:
import { reduce, addIndex } from 'ramda';
const reduceWithIndex = addIndex(reduce)((final, word, index) => {
const found = final.find(({ value }) =>
value.toLowerCase() === word.toLowerCase()
);
if (found) {
found.count++;
found.indexes.push(index);
} else {
final.push({
value: word.toLocaleLowerCase(),
count: 1,
indexes: [index],
});
}
return final;
});
export default words => reduceWithIndex([], words);
Thomas 的诊断非常准确。但我会选择一个稍微不同的修复:
import { reduce, addIndex, append } from 'ramda';
const reduceWithIndex = addIndex(reduce);
export default reduceWithIndex((final, word, index) => {
const found = final.find(({ value }) =>
value.toLowerCase() === word.toLowerCase()
);
if (found) {
found.count++;
found.indexes.push(index);
return final;
}
return append({
value: word.toLocaleLowerCase(),
count: 1,
indexes: [index],
}, final);
}, []);
函数式编程涉及很多方面,但最重要的方面之一是不可变数据结构。尽管没有什么能阻止您改变累加器对象并将其传回您的 reducer 函数,但我发现它的风格很差。相反,总是 return 一个新对象,你不会有这样的问题。 Ramda 的所有功能都是基于这个原则构建的,所以当使用 append
时,你会自动得到一个新列表。
我还建议更改 if
块以避免 found
对象的内部突变。我会把它留作练习,但如果很难做到,请随时 ping。
你可以在 Ramda REPL 中看到 original solution and the altered version 之间的区别。
我注意到,如果我使用 ramda
,有时我会在尝试为我正在导出的方法编写 Jest
测试时遇到问题。我已经将问题归结为以下测试和两个基本的减速器功能。我已将它们张贴在 gist
上,以免代码堵塞这个问题。
https://gist.github.com/beardedtim/99aabe3b08ba58037b20d65343ed9d20
我在使用 ramda
reducer 时遇到以下错误:
● counter usage › counter counts the words and their index in the given list of words
expect(received).toEqual(expected)
Expected value to equal:
[{"count": 3, "indexes": [0, 2, 4], "value": "a"}, {"count": 1, "indexes": [1], "value": "b"}, {"count": 1, "indexes": [3], "value": "c"}]
Received:
[{"count": 15, "indexes": [0, 2, 4, 0, 2, 4, 0, 2, 4, 0, 2, 4, 0, 2, 4], "value": "a"}, {"count": 5, "indexes": [1, 1, 1, 1, 1], "value": "b"}, {"count": 5, "indexes": [3, 3, 3, 3, 3
], "value": "c"}]
这让我相信 ramda
的 reduce 是保持某种状态或彼此共享 words
。我不确定这是怎么回事。任何人都知道我应该用谷歌搜索什么或者其他 docs/examples 处理这个的人?
状态数组 (final
) 硬连接到 reduceWithIndex
。对此函数的所有调用共享同一个 final
数组。
试试这个:
import { reduce, addIndex } from 'ramda';
const reduceWithIndex = addIndex(reduce)((final, word, index) => {
const found = final.find(({ value }) =>
value.toLowerCase() === word.toLowerCase()
);
if (found) {
found.count++;
found.indexes.push(index);
} else {
final.push({
value: word.toLocaleLowerCase(),
count: 1,
indexes: [index],
});
}
return final;
});
export default words => reduceWithIndex([], words);
Thomas 的诊断非常准确。但我会选择一个稍微不同的修复:
import { reduce, addIndex, append } from 'ramda';
const reduceWithIndex = addIndex(reduce);
export default reduceWithIndex((final, word, index) => {
const found = final.find(({ value }) =>
value.toLowerCase() === word.toLowerCase()
);
if (found) {
found.count++;
found.indexes.push(index);
return final;
}
return append({
value: word.toLocaleLowerCase(),
count: 1,
indexes: [index],
}, final);
}, []);
函数式编程涉及很多方面,但最重要的方面之一是不可变数据结构。尽管没有什么能阻止您改变累加器对象并将其传回您的 reducer 函数,但我发现它的风格很差。相反,总是 return 一个新对象,你不会有这样的问题。 Ramda 的所有功能都是基于这个原则构建的,所以当使用 append
时,你会自动得到一个新列表。
我还建议更改 if
块以避免 found
对象的内部突变。我会把它留作练习,但如果很难做到,请随时 ping。
你可以在 Ramda REPL 中看到 original solution and the altered version 之间的区别。