代码之家  ›  专栏  ›  技术社区  ›  J. Hesters

Ramda:如何基于对象的其他值只更改对象的一个值

  •  0
  • J. Hesters  · 技术社区  · 7 年前

    如果你想看到完整的代码,我还请求帮助 StackExchange Code Review .

    不过,对于堆栈溢出,只有一个部分是相关的。

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

    上下文: 我有一个对象,它表示一个与多个键的接触,这些键都是字符串。对象总是有一个名为 contactDetails . 我想计算 取决于对象的 tel , bday email

    如果联系人在函数之前是这样的:

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

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

    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
    ),
    

    map . 有没有更好的方法可以基于对象的其他值在Ramda中更改对象的值?

    0 回复  |  直到 7 年前
        1
  •  4
  •   Scott Sauyet    7 年前

    除非这是一个学习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))

    此版本不依赖于密钥 contactDetails 已经存在,尽管它在那里不会伤害你。

    bday tel 是供应的,但是 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])
    })
    

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

        2
  •  2
  •   Scott Christopher    7 年前

    R.assoc('contactDetails') R.juxt R.propOr('') 若要默认任何缺少的属性,请在将空字符串与 R.join .

    // takes a list of property names, returning a function that accepts an object
    // and produces a list of the values of the provided properties, defaulting to
    // an empty string if null or undefined.
    const defProps =
      R.compose(R.juxt, R.map(R.propOr('')))
    
    const fn =
      // When `g` is a function, `R.chain(f, g)(x)` is equivalent to `f(g(x), x)`
      R.chain(
        R.assoc('contactDetails'),
        R.pipe(
          defProps(['bday', 'tel', 'email']),
          R.reject(R.equals('')),
          R.join(' ')))
    
    console.log(fn({
      firstName: 'John',
      lastName: 'Doe',
      contactDetails: '',
      tel: '555-55-5555',
      bday: '',
      email: 'john@doe.com'
    }))
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
        3
  •  1
  •   Ori Drori    7 年前

    可以使用R.converge合并原始对象,以及生成 contactDetails

    const { converge, merge, identity, pipe, props, filter, join, trim, objOf } = R
    
    const fn = converge(merge, [identity, pipe(
      props(['bday', 'tel', 'email']),
      filter(Boolean),
      join(' '),
      objOf('contactDetails')
    )])
    
    const obj = {
      firstName: 'John',
      lastName: 'Doe',
      contactDetails: '',
      tel: '555-55-5555',
      bday: '',
      email: 'john@doe.com'
    }
    
    const result = fn(obj)
    
    console.log(result)
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
    推荐文章