Ramda:如何根据对象的其他值仅更改对象的一个​​值

J. *_*ers 0 javascript functional-programming ramda.js

我正在构建一个 React 应用程序。我正在使用 Ramda 来帮助我进行函数式编程。

如果您想查看完整代码,我还在StackExchange Code Review上寻求帮助。

但是,对于 Stack Overflow,只有一部分是相关的。

如何使用 Ramda 根据对象的其他值更改对象的特定值?我mapObjIndexed在过程中使用which 映射所有键。

上下文:我有一个对象,它代表一个带有几个都是字符串的键的联系人。该对象始终有一个名为 的键contactDetails。我想计算contactDetails对象的tel,bdayemail键的值的依赖值。

如果一个联系人在函数之前看起来像这样:

{
  firstName: 'John',
  lastName: 'Doe',
  contactDetails: '',
  tel: '555-55-5555',
  bday: '',
  email: 'john@doe.com'
}
Run Code Online (Sandbox Code Playgroud)

之后它应该是这样的:

{
  firstName: 'John',
  lastName: 'Doe',
  contactDetails: 'john@doe.com 555-55-5555',
  tel: '555-55-5555',
  bday: '',
  email: 'john@doe.com'
}
Run Code Online (Sandbox Code Playgroud)

我为此编写的函数如下所示:

R.mapObjIndexed((val, key, obj) =>
  key === 'contactDetails'
    ? R.trim(
        R.replace(
          /undefined/g,
          '',
          `${R.prop('bday')(obj)} ${R.prop('tel')(obj)} ${R.prop('email')(
            obj
          )}`
        )
      )
    : val
),
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,这是一种非常不干净和 hacky 的滥用map. 有没有更好的方法可以根据对象的其他值在 Ramda 中更改对象的值?

Sco*_*yet 5

除非这是学习 Ramda 的练习,否则我建议比您可能从 Ramda 中想到的任何技术都更简单的技术是直接的对象解构方法:

const transform = ({tel, bday, email, ...rest}) => ({
  ...rest, tel, bday, email,
  contactDetails: [bday, email, tel].join(' ').trim()
})

const obj = {firstName: 'John', lastName: 'Doe', tel: '555-55-5555', bday: '', email: 'john@doe.com'}

console.log(transform(obj))
Run Code Online (Sandbox Code Playgroud)

这个版本不依赖于contactDetails已经存在的密钥,尽管它在那里不会有什么坏处。

如果您真的担心单词之间可能存在双空格(例如,如果提供了bdaytel,但email为空),您可以将其修改为:

const combine = (ss) => ss.reduce((a, s) => a + (s.length ? ' ' : '') + s, '').trim()

const transform = ({tel, bday, email, ...rest}) => ({
  ...rest, tel, bday, email,
  contactDetails: combine([bday, email, tel])
})
Run Code Online (Sandbox Code Playgroud)

我是 Ramda 的创始人之一,也是一个大粉丝,但它只是一个工具包。有很多地方它有助于使您的代码更易于阅读和编写;无论如何,请使用它。但是当它不这样做时,即使在大量使用 Ramda 的代码库中,也可以跳过它并使用其他技术。