如何使用Ramda将对象映射转换为数组?

问题描述 投票:1回答:2

我想转换以下对象:

{
  'id-1': { prop: 'val1' },
  'id-2': { prop: 'val2' },
}

要数组:

[
  { id: 'id-1', prop: 'val1' },
  { id: 'id-2', prop: 'val2' },
]

到目前为止我做了什么(它有效):

R.pipe(
  R.toPairs,
  R.map(([id, props]) => ({
    id,
    ...props,
  }))
)

我想只使用Ramda来解决它 - 如果可能的话。

javascript functional-programming ramda.js
2个回答
3
投票

我建议解决它“仅使用Ramda”是一个糟糕的设计目标,除非这是一个学习Ramda的练习。我是Ramda的创始人之一,也是一个忠实的粉丝,但Ramda只是一个旨在简化代码的工具包,使其更容易在某种范例中工作。

也就是说,我们当然可以使用Ramda编写一个无点版本。我想到的第一件事就是这个*:

const transform = pipe(
  toPairs,
  map(apply(useWith(merge, [objOf('id'), identity])))
)

const data = {'id-1': { prop: 'val1' }, 'id-2': { prop: 'val2'}}

console.log(transform(data))
<script src="https://bundle.run/[email protected]"></script><script>
const {pipe, toPairs, map, apply, useWith, merge, objOf, identity} = ramda    </script>

但这比你原来的可读性低,而不是更多。

这段代码:

const transform = pipe(
  toPairs,
  map(([id, props]) => ({...props, id}))
)

是清楚的,而Ramda版本要求人们了解Ramda特定的useWithobjOf和略微模糊的apply - 我希望mapmergeidentity是清楚的。

事实上,这段代码很简单,我可能会把它写成一个单行,在这种情况下,我切换到compose pipe

const transform = compose(map(([id, props]) => ({...props, id})), toPairs)

但我可能不会这样做,因为我发现多行pipe版本更容易阅读。

最后请注意,我们可以在没有任何Ramda工具的情况下以相当可读的方式执行此操作:

const transform = (data) => 
  Object.entries(data).map(
    ([id, props]) => ({...props, id})
  )

如果我已经在我的代码库中使用Ramda,我更喜欢上面的pipe版本;我觉得它更容易阅读。但是,永远不会将Ramda引入项目只是为了那个相当小的差异。

我担心人们会对无点代码产生迷恋。这是一个工具。在使代码更易理解时使用它。当它使您的代码更加模糊时,请跳过它。在这里,我认为你从相当可读的代码开始;它很难改进。


*请注意,这里的identity不是绝对必要的;你可以跳过它而不会有任何伤害。没有useWithidentity生成的函数将错误地报告1的arity,但由于函数立即用apply包裹,然后进一步放置在从toPairs接收双元素数组的上下文中,没有什么依赖于元数。但我发现无论如何要包括它都是一个好习惯。


1
投票

那这个呢?可能不那么冗长!

const toArray = R.pipe(
  R.toPairs,
  R.map(
    R.apply(R.assoc('id')),
  ),
);

const data = {
  'id-1': { prop: 'val1' },
  'id-2': { prop: 'val2' },
};

console.log('result', toArray(data));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
© www.soinside.com 2019 - 2024. All rights reserved.