简体   繁体   中英

How to transform object map to array with Ramda?

I'd like to transfrom the following object:

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

To array:

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

What I have done so far (it works):

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

I'd like to solve it using Ramda only - if possible.

I'd suggest that solving it "using Ramda only" is a bad design goal, unless this is an exercise in learning Ramda. I'm one of the founders of Ramda and a big fan, but Ramda is only a toolkit meant to simplify your code, to make it easier to work in a certain paradigm.

That said, we could certainly write a point-free version of this using Ramda. The first thing that comes to my mind would be this * :

 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/ramda@0.26.1"></script><script> const {pipe, toPairs, map, apply, useWith, merge, objOf, identity} = ramda </script> 

But this is less readable than your original, not more.

This code:

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

is crystal-clear, whereas that Ramda version requires one to understand Ramda-specific useWith and objOf and slightly obscure apply -- I would hope that map , merge , and identity are clear.

In fact, this code is simple enough that I might well write it as a one-liner, in which case, I switch to compose over pipe :

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

But I probably wouldn't do so, as I find that multi-line pipe version easier to read.

Finally note that we can do this in a fairly readable way without any Ramda tools at all:

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

If I was already using Ramda in my code-base, I would prefer the pipe version above to this; I think it's somewhat easier to read. But would never introduce Ramda into a project only for that fairly minor difference.

I worry that people make a fetish over point-free code. It's a tool. Use it when it makes your code more understandable. Skip it when it makes your code more obscure. Here I think you're starting from quite readable code; it's difficult to improve on it.


* Note that identity here is not strictly necessary; you can skip it with no harm. The function generated by useWith without that identity will incorrectly report an arity of 1, but since the function is immediately wrapped with apply and then further placed in the context of receiving the a two-element array from toPairs , there is nothing which depends upon that arity. But I find it a good habit to include it regardless.

what about this? probably less verbose!

 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> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM