如何处理子操作并保持 Ramda 的功能?

How to handle sub-operations and keep functional with Ramda?

如何使用 ramda 解决单个处理管道中的子操作?假设我有一个数字数组,并且想要 return 每个数字在总数中所占百分比的数组:

const values = [1, 5, 8, 2, 5]

// 1 - Get total: 1 + 5 + 8 + 2 + 5 = 21
// 2 - Return percentages of each item:
//
// 2.1 - 1: (1 * 100) / 21 = 4.761904762%
// 2.2 - 5: (5 * 100) / 21 = 23.80952381%
// 2.3 - 8: (5 * 100) / 21 = 38.095238095%
// 2.4 - 2: (5 * 100) / 21 = 9.523809524
// 2.5 - 5: (5 * 100) / 21 = 23.80952381%
percents(values) // [4.76, 23,80, 9.52, 23,80]

我可以使用单个 Ramda 解决这个问题吗pipe/composition?

你可以这样做:

const {compose, map, multiply, chain, flip, divide, sum} = R

const percentages = chain(tot => values => map(val =>  100 * val / tot, values), sum)
console.log(percentages([1, 5, 8, 2, 5]))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>

这也可以写得更紧凑一些

const percentages = chain(compose(map, tot => val => 100 * val / tot), sum)

如果你想去 point-free,我想这也行:

const percentages = compose(map(multiply(100)), chain(compose(map, flip(divide)), sum))

尽管我觉得它的可读性较差。

备注

这是一个单一的管道作为代码,但是应用于函数的chain 类似于chain(f, g)(x) //~> f(g(x), x)。 (从技术上讲,这不是真的,它更像是 chain(f, g)(x) //~> f(g(x))(x),但通常在 Ramda 中,它们是相似的。)所以你的值会有两次单独的迭代,一次计算总数,一次计算每个百分比给定价值和总数。当然,这在数学上是必不可少的。您无法计算总和并同时使用该总和,但我不想在这里混淆单个管道的概念。