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 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.
R.map
.
– haxpanel
Commented
Apr 24, 2019 at 11:22
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 es 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/[email protected]"></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 pose
over pipe
:
const transform = pose(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./ajax/libs/ramda/0.26.1/ramda.js"></script>