给定一个包含这种形式的对象的数组:
[{data: {set: 'set1', option: 'option1'}},
{data: {set: 'set1', option: 'option2'}},
{data: {set: 'set1', option: 'option3'}},
{data: {set: 'set2', option: 'optionA'}},
{data: {set: 'set2', option: 'optionB'}}]
如何获得如下所示的数组:
[{set: 'set1', options: ['option1', 'option2', 'option3']},
{set: 'set2', options: ['optionA', 'optionB']}]
我想使用函数式编程,Ramda或本机JS方法。感谢。
答案 0 :(得分:3)
我喜欢在几个步骤中考虑这样的问题,这些步骤一直让我朝着我想要的输出方向前进。有时这意味着我会错过一个更优雅的解决方案,但它通常会让我更容易想出一些有效的方法。
所以让我们用Ramda这样看看你的问题。
您不需要外部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"}
]
这是一个好的开始。现在我们需要考虑将它们组合成类似的组。
我们希望将共享其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"}
]
}
那里有冗余信息。在某个地方,我们需要弄明白这一点。但是当我试图将其他部分拉到一起时,我会保留一点。
我们已经看过pluck
。看起来我们可以在set1
和set2
上使用它。好map
也适用于对象,所以如果我们只是在最后调用map(pluck('option'))
,我们就会得到这个:
{
set1: ["option1", "option2", "option3"],
set2: ["optionA", "optionB"]
}
哦,看,那也摆脱了冗余。这看起来非常接近所需的输出。
但是现在我没有看到内置的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"]
}
]
好的,现在我们必须把它们放在一起。 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
里面的后面的行,看看早先的行。
我在那里构建了代码,一次向管道添加一行,直到我转换了数据。我认为这是一种很好的工作方式。