【发布时间】:2019-02-12 18:03:14
【问题描述】:
我正试图将我的头脑集中在 Ramda 和函数式编程上,看看它在我的情况下是否有意义。
下面是我需要解决的典型问题:
以下作为输入数据:
const values = [
{ a: 1, b: 2, c: 3 },
{ a: 10, b: 20, c: 30 },
...
{ a: 100, b: 200, c: 300 }
]
以下函数应用于数据:
const eFn = x => x.a + x.b
const fFn = ? // cumulative add: Sum of the e keys from first to current index, first iteration f = 3, then 3 + 30, then 3 + 30 +300
const gFN = x => x.f > x.e
在这个给定的序列中:
- eFn()
- fFn()
- gFn()
结果如下:
const results = [
{ a: 1, b: 2, c: 3, e: 3, f: 3, g: true },
{ a: 10, b: 20, c: 30, e: 30, f: 33, g: true },
...
{ a: 100, b: 200, c: 300, e: 300, f: 333, g: false }
]
问题:
对于这类问题,
- 使用 ramda 有意义吗?
- 它是否简化了问题,并且知道 fFn 依赖于前几行的数据并且必须在 fFn 之后应用 gFn 时,我是否可以避免在数据上循环多次?
我发现使用 Ramda 很难很好地解决这个问题。
我们将不胜感激。
更新 (2019-02-12)
基于@scott-sauyet 的回答,我确实尝试对 Ramda 与 Rambda 进行基准测试。 由于我无法 100% 复制他的测试,因此我对其进行了修改以更改 fFn 的行为并手动设置应用每个函数的次数。
const {floor, random} = Math
const demo = counts => {
const eFns = R.curry((n, x) => R.assoc(`e${n}`, x.a + x.b, x))
const fFns = R.curry((n, x) => R.assoc(`f${n}`, x.d * x.b, x))
const gFns = R.curry((n, x) => R.assoc(`g${n}`, x.f > x.e, x))
const transform = R.pipe(
R.map(eFns(1)),
R.map(eFns(2)),
R.map(eFns(3)),
R.map(eFns(4)),
R.map(eFns(5)),
R.map(eFns(6)),
R.map(eFns(7)),
R.map(eFns(8)),
R.map(eFns(9)),
R.map(eFns(10)),
R.map(eFns(12)),
R.map(eFns(13)),
R.map(eFns(14)),
R.map(eFns(15)),
R.map(eFns(16)),
R.map(eFns(17)),
R.map(eFns(18)),
R.map(eFns(19)),
R.map(eFns(20)),
R.map(eFns(21)),
R.map(eFns(22)),
R.map(eFns(23)),
R.map(eFns(24)),
R.map(eFns(25)),
R.map(eFns(26)),
R.map(eFns(27)),
R.map(eFns(28)),
R.map(eFns(29)),
R.map(eFns(30)),
R.map(eFns(31)),
R.map(eFns(32)),
R.map(eFns(33)),
R.map(eFns(34)),
R.map(eFns(35)),
R.map(eFns(36)),
R.map(eFns(37)),
R.map(eFns(38)),
R.map(eFns(39)),
R.map(eFns(40)),
R.map(fFns(1)),
R.map(fFns(2)),
R.map(fFns(3)),
R.map(fFns(4)),
R.map(fFns(5)),
R.map(fFns(6)),
R.map(fFns(7)),
R.map(fFns(8)),
R.map(fFns(9)),
R.map(fFns(10)),
R.map(gFns(1)),
R.map(gFns(2)),
R.map(gFns(3)),
R.map(gFns(4)),
R.map(gFns(5)),
R.map(gFns(6)),
R.map(gFns(7)),
R.map(gFns(8)),
R.map(gFns(9)),
R.map(gFns(10))
)
const vals = R.times(n => ({
a: floor(random() * 1000),
b: floor(random() * 1000),
c: floor(random() * 1000),
d: floor(random() * 1000)
}), counts)
const now = new Date()
transform(vals)
const time = new Date() - now
console.log(`Ran ${counts} records through ${eFns.length} e's, ${fFns.length} f's, and ${gFns.length} g's in ${time} ms`)
}
console.clear()
demo(10)
demo(100)
demo(1000)
demo(10000)
demo(100000)
现在,我将此代码依次粘贴到 Ramda REPL 和 Rambda REPL。我在 Windows 7、带有 Chrome 66 的核心 i7-6820HQ 和 Node.js v8.11.1 上运行了测试。
令我惊讶的是,就我而言,Rambada 比 Ramda 慢。请注意,这是一个快速而肮脏的测试,我可能错过了为 Rambda 设置测试的正确方法(我只是想复制并粘贴每个 REPL 中的代码并通过修改 import 语句在节点中运行)。
这是我的结果: (注意图表是对数对数比例)
Record Number [-] : 10 | 10 | 1000 | 10000 | 10000
Ramda Chrome 66 [time in ms] : 5 | 39 | 329 | 3673 | 38910
Rambda Chrome 66 [time in ms] : 6 | 85 | 530 | 5306 | 53777
Ramda Node.js [time in ms] : 8 | 38 | 396 | 4219 | 45621
Rambda Node.js [time in ms] : 7 | 62 | 537 | 5468 | 57540
【问题讨论】:
标签: javascript ramda.js