I'm trying to write code using Ramda to produce a new data structure, using only the id
and comment
keys of the original objects. I'm new to Ramda and it's giving me some fits, although I have experience with what I think is similar coding with Python.
Given the following initial data structure…
const commentData = {
'30': {'id': 6, 'comment': 'fubar', 'other': 7},
'34': {'id': 8, 'comment': 'snafu', 'other': 6},
'37': {'id': 9, 'comment': 'tarfu', 'other': 42}
};
I want to transform it into this…
{
'6': 'fubar',
'8': 'snafu',
'9': 'tarfu'
}
I found the following example in the Ramda cookbook that comes close…
const objFromListWith = R.curry((fn, list) => R.chain(R.zipObj, R.map(fn))(list));
objFromListWith(R.prop('id'), R.values(commentData));
But values it returns includes the whole original object as the values…
{
6: {id: 6, comment: "fubar", other: 7},
8: {id: 8, comment: "snafu", other: 6},
9: {id: 9, comment: "tarfu", other: 42}
}
How can I reduce the values down to the value of their comment
key only?
I don't need to use the code I got from the cookbook. If anyone can suggest some code that will give the results I'm looking for that's also better (simpler, shorter, or more efficient) than the example here, I'll be happy to use that instead.
If you don't mind, you don't need to use Ramda for that, pure JS can handle it nicely:
You can use a combination of Object.values()
, to get all values of your first object (commentData
) and .forEach()
(or even .map()
, but slower), in the array that results from Object.values
to insert values into a new object dynamically.
const commentData = {
'30': {'id': 6, 'comment': 'fubar', 'other': 7},
'34': {'id': 8, 'comment': 'snafu', 'other': 6},
'37': {'id': 9, 'comment': 'tarfu', 'other': 42}
};
let values = Object.values(commentData)
let finalObj = {};
values.forEach(x => finalObj[x.id] = x.comment)
console.log(finalObj)
But, if you want an one-liner, you can go with Object.fromEntries()
after returning arrays of key/value from .map()
based on id
and comment
, like below:
const commentData = {
'30': {'id': 6, 'comment': 'fubar', 'other': 7},
'34': {'id': 8, 'comment': 'snafu', 'other': 6},
'37': {'id': 9, 'comment': 'tarfu', 'other': 42}
};
console.log(Object.fromEntries(Object.values(commentData).map(x => [x.id, x.comment])))
A Ramda one-liner would be
const foo = compose(fromPairs, map(props(['id', 'comment'])), values)
const commentData = {
'30': {'id': 6, 'comment': 'fubar', 'other': 7},
'34': {'id': 8, 'comment': 'snafu', 'other': 6},
'37': {'id': 9, 'comment': 'tarfu', 'other': 42}
}
console.log(
foo(commentData)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script>const {compose, fromPairs, map, props, values} = R </script>
But that doesn't seem a lot cleaner than (a slight tweak to) the suggestion in epascarello's comment:
const foo = (obj) =>
Object.values(obj).reduce((o, v) => (o[v.id] = v.comment) && o, {})
or a similar version I would write, if it didn't cause any performance issues:
const foo = (obj) =>
Object.values(obj).reduce((o, {id, comment}) => ({...o, [id]: comment}), {})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With