在对象上执行功能,然后在 Ramda 中操作对象

Performing function on object and then manipulating the object in Ramda

我正在努力学习一些 ramda 逻辑,我觉得我几乎掌握了它,但我的大脑今天不能正常工作。

我有一个对象:

const thing = {
  'name': 'thing',
  'value': 1000.0987654321,
  'valueAsString': "1000.0987654321",
  'otherThings': { 'blah': 'blah' },
}

我想从事物中提取 'name' 和 'value',但我想在返回我的新对象之前对值进行舍入。

我知道要提取名称和值,我可以使用 pick: R.pick(['name', 'value']) 并执行我的舍入函数,我可以采用现有的舍入函数:

const roundTo9Dp = (n) => Number((n).toFixed(9))

并将其应用于我的对象,如下所示:R.compose(roundTo9Dp, R.prop('value'))

这两个操作独立工作:

const picker = R.pick(['name', 'value'])
picker(thing) // => {"name": "thing", "value": 1000.0987654321}

const rounded = R.compose(roundTo9Dp, R.prop('value'))
rounded(thing) // => 1000.098765432

当我加入他们的时候,我很挣扎。就像他们在 'thing' 上以不同的级别进行操作,而我只是在努力解除他们的选择。

R.compose(picker, R.assoc('value', rounded))(thing) // Incorrect
picker(R.compose(R.assoc('value'), rounded)(thing)(thing)) // works, but is hideous

您可以通过多种方式使用 Ramda 执行此操作。这里有一些:

const roundTo9Dp = (n) => Number((n).toFixed(9))

const foo1 = applySpec({
  name: prop('name'),
  value: compose(roundTo9Dp, prop('value'))
})

const foo2 = pipe(
  pick (['name', 'value']),
  over (lensProp ('value'), roundTo9Dp)
)

const rounded = R.compose(roundTo9Dp, R.prop('value'))
const foo3 = pipe(
  pick (['name', 'value']),
  chain(assoc('value'), rounded)
)

const foo4 = pipe(
  props (['name', 'value']),
  zipWith (call, [identity, roundTo9Dp]),
  zipObj (['name', 'value'])
)

const thing = {name: 'thing', value: 1000.0987654321, valueAsString: "1000.0987654321", otherThings: {blah: 'blah'}}

console .log ('foo1:', foo1 (thing))
console .log ('foo2:', foo2 (thing))
console .log ('foo3:', foo3 (thing))
console .log ('foo4:', foo4 (thing))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
<script> const {applySpec, prop, compose, pipe, pick, over, lensProp, chain, assoc, props, zipWith, call, identity, zipObj} = R </script>

如果我们尝试的话,我们可以想出更多。 foo3 可能最接近您遇到的问题。 chain when applied to functions works like chain (f, g) (x) //=> f (g (x)) (x), which would avoid the ugly (thing) (thing) in your version. This version might teach you some about the world of FantasyLand typeclasses. foo1 uses one of Ramda's more convenient object manipulation functions, applySpec. foo2 uses lensProp and over, which can lead you into the fascinating world of lenses. And foo4, while probably not recommended, shows off zipWith and zipObj,用于组合列表的函数。

但是除非这是关于学习 Ramda,否则我会建议 none 这些,因为这很简单,在现代 JS 中不需要任何库:

const foo = ({name, value}) => 
  ({name, value: roundTo9Dp(value)})

我是 Ramda 的创始人之一,我仍然是它的忠实粉丝。但我认为它是一个库,当它使代码更清晰和更易于维护时可以使用。这里,最简单的版本不需要。