我喜欢通过几个步骤来思考这样的问题,这些步骤不断推动我朝着我想要的输出方向前进。有时这意味着我错过了一个更优雅的解决方案,但它通常更容易想出一些可行的方法。
那么让我们用 Ramda 来看看你的问题。
第 1 步:删除不必要的数据
你不想要那个外部的data 属性。由于您的数据是一个对象列表,并且每个对象都有一个 data 属性来保存我们想要的数据,因此我们可以简单地对每个对象调用 prop('data')。
要调用每一个,我们可以使用map,给我们map(prop('data'))。
因为这是一个很常见的用法,Ramda 还提供了一个将map 和prop 这样组合的函数:pluck('data')。将其应用于您的输入,我们得到:
[
{option: "option1", set: "set1"},
{option: "option2", set: "set1"},
{option: "option3", set: "set1"},
{option: "optionA", set: "set2"}
{option: "optionB", set: "set2"}
]
这是一个好的开始。现在我们需要考虑将它们组合成类似的组。
第 2 步:对数据进行分组
我们希望将共享其set 属性的所有元素组合在一起。 Ramda 提供groupBy,它接受一个将项目转换为分组键的功能。我们想按set 属性进行分组,因此我们可以再次使用prop,并针对之前的结果调用groupBy(prop('set'))。
这会产生:
{
set1: [
{option: "option1", set: "set1"},
{option: "option2", set: "set1"},
{option: "option3", set: "set1"},
],
set2: [
{option: "optionA", set: "set2"}
{option: "optionB", set: "set2"}
]
}
里面有多余的信息。我们需要在某个地方弄清楚这一点。但是我会在尝试将其他部分组合在一起时将其保存一点。
第 3 步:组合选项
我们已经看到pluck。看起来我们可以在set1 和set2 上使用它。 map 也适用于对象,所以如果我们在最后一个调用 map(pluck('option')),我们会得到:
{
set1: ["option1", "option2", "option3"],
set2: ["optionA", "optionB"]
}
哦,看,这也摆脱了冗余。这看起来非常接近所需的输出。
第 4 步:重建对象
但现在我没有看到内置的 Ramda 函数可以让我一路走好。我可以写一个自定义的。或者我可以分两步进行转换。知道我想使用 Ramda 的zipObj 函数,我可以先将上面的通过toPairs 转换为数组,生成这个:
[
["set1", ["option1", "option2", "option3"]],
["set2", ["optionA", "optionB"]]
]
然后我可以将zipObj 映射到我希望每个属性具有的键的结果上。这意味着我可以致电map(zipObj(['set', 'options'])) 来获得最终想要的结果:
[
{
set: "set1",
options: ["option1", "option2", "option3"]
},
{
set: "set2",
options: ["optionA", "optionB"]
}
]
第 5 步:将所有内容放在一起
好的,现在我们必须把这些放在一起。 Ramda 有pipe 和compose。我通常只在适合一行时选择compose。因此,将这些与pipe 合并,我们可以这样写:
const transform = pipe(
pluck('data'),
groupBy(prop('set')),
map(pluck('option')),
toPairs,
map(zipObj(['set', 'options']))
)
然后就叫它
transform(myObj)
您可以在 Ramda REPL 上看到这一点。在那里,您可以注释掉 pipe 中后面的行,看看前面的行做了什么。
我在那里构建了代码,一次向管道添加一行,直到我转换了数据。我认为这是一种很好的工作方式。