【问题标题】:Ramda: Duplicate an object by its (array) propertyRamda:通过其(数组)属性复制对象
【发布时间】:2018-10-14 21:53:26
【问题描述】:

我有一个具有数组属性{ property: [a, b] } 的对象,我想要一个重复对象列表,其中[{ property: [a] }, { property: [b] }]

输入是:

const input = {
  url: 'getting-started',
  locales: ['en-GB', 'en-JP']
}

预期形式是:

const expected = [{
  url: 'getting-started',
  locales: ['en-GB']
}, {
  url: 'getting-started',
  locales: ['en-JP']
}]

我写的函数有点不可读,甚至不纯:

const duplicateByLocales = article => R.pipe(
  R.prop('locales'),
  R.invert,
  R.mapObjIndexed((val, locale) =>
    R.pipe(
      R.clone,
      R.assoc('locales', R.of(locale))
    )(article)),
  R.values
)(article)

它确实有效,但我很好奇更好的方法是什么样的?谢谢!

【问题讨论】:

  • 我已编辑您的问题以修复代码格式。为了将来参考,SO 不使用通常的降价约定进行格式化:代码块通过将所有内容缩进 4 个空格来标记(我知道,这很奇怪)。您还可以突出显示代码块并按 ctrl-k(在 mac 上为 cmd-k),它会为您完成。
  • 为什么输出有locales: ['en-GB']而不是locale: 'en-GB'
  • @ScottSauyet 你说得对,应该是locale: 'en-GB'!我的疏忽

标签: javascript functional-programming ramda.js


【解决方案1】:

你可以这样做:

const input = {
  url: 'getting-started',
  locales: ['en-GB', 'en-JP']
}

let result = input.locales.map(locale => ({...input, locales:[locale]}));
console.log(result);

请记住,{...input} 创建了 input 的浅表副本。如果input 有多个级别,这会变得有点复杂。

我们可以为它写一个函数

const transform = input =>
  input.locales.map(locale => ({...input, locales:[locale]}))

console.log(transform({
  url: 'getting-started',
  locales: ['en-GB', 'en-JP']
}))

【讨论】:

  • 很好,我从来没有想过在传播之后覆盖这样的密钥。很惊讶这不会进入严格模式,但显然不是(只是在严格模式 IIFE 中在 chrome 中尝试过)。
  • 谢谢你这绝对是一个改进,但我试图找到一种纯粹的方法,你的函数是指外部上下文(...input)。所以我认为理想情况下该函数将获取对象,并返回一个数组。
  • 这不是一个函数,而是一个表达式。通过const tranform = input => input.locales.map(...) 之类的方式将其转换为函数,我们确实得到了一个纯函数。
  • 如果您更喜欢 locale: 'en-JP' 而不是 locales: ['en-JP'] 在结果对象列表中,您可以调整答案中的 transform 函数,如下所示:({locales, ...rest}) => locales.map(locale => ({locale, ...rest}))
猜你喜欢
  • 2020-02-29
  • 1970-01-01
  • 2021-11-23
  • 1970-01-01
  • 2013-11-19
  • 2019-05-29
  • 1970-01-01
  • 2013-06-06
  • 2019-08-22
相关资源
最近更新 更多