const orignalArr = [
{
personName: 'Joe'
}
]
expected output:
const convertedArr = [
{
name: 'Joe'
}
]
I'm thinking the renamed keys are defined in an object (but fine if there's a better way to map them):
const keymaps = {
personName: 'name'
};
How can I do this with Ramda?
Something with R.map
const orignalArr = [
{
personName: 'Joe'
}
]
expected output:
const convertedArr = [
{
name: 'Joe'
}
]
I'm thinking the renamed keys are defined in an object (but fine if there's a better way to map them):
const keymaps = {
personName: 'name'
};
How can I do this with Ramda?
Something with R.map
5 Answers
Reset to default 14There is an entry in Ramda's Cookbook for this:
const renameKeys = R.curry((keysMap, obj) =>
R.reduce((acc, key) => R.assoc(keysMap[key] || key, obj[key], acc), {}, R.keys(obj))
);
const originalArr = [{personName: 'Joe'}]
console .log (
R.map (renameKeys ({personName: 'name'}), originalArr)
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
But with the ubiquity of ES6, it's pretty easy to write this directly:
const renameKeys = (keysMap) => (obj) => Object.entries(obj).reduce(
(a, [k, v]) => k in keysMap ? {...a, [keysMap[k]]: v} : {...a, [k]: v},
{}
)
You can combine Ramda with Ramda Adjunct. Using the renameKeys
(https://char0n.github.io/ramda-adjunct/2.27.0/RA.html#.renameKeys) method is very useful. With it you can simply do something like this:
const people = [
{
personName: 'Joe'
}
]
const renameKeys = R.map(RA.renameKeys({ personName: 'name' }));
const __people__ = renameKeys(people);
console.log(__people__) // [ { name: 'Joe' }]
Hope it helped you :)
This is my take on renameKeys
. The main idea is to separate the keys and values to two array. Map the array of keys, and replace with values from keyMap
(if exist), then zip back to object:
const { pipe, toPairs, transpose, converge, zipObj, head, map, last } = R
const renameKeys = keysMap => pipe(
toPairs, // convert to entries
transpose, // convert to array of keys, and array of values
converge(zipObj, [ // zip back to object
pipe(head, map(key => keysMap[key] || key)), // rename the keys
last // get the values
])
)
const originalArr = [{ personName: 'Joe', lastName: 'greg' }]
const result = R.map(renameKeys({ personName: 'name' }), originalArr)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
My idea to make it is to first check that the old prop I want to rename exists, and the new key I want to create doesn’t.
Then, I will use the S_
common combinator to make it point-free.
Find JS common combinators here
const {
allPass, assoc, compose: B, complement, has, omit, prop, when
} = require('ramda');
const S_ = (f) => (g) => (x) => f (g (x)) (x);
const renameKey = (newKey) => (oldKey) => when(allPass([
has(oldKey)
, complement(has)(newKey)
]))
(B(omit([oldKey]), S_(assoc(newKey))(prop(oldKey))))
const obj = { fullname: 'Jon' };
renameKey('name')('fullname')(obj) // => { name: ‘Jon’ }
Here is my own solution, not too many arrow functions (just one), mostly pure Ramda calls. And it is one of shortest, if not the shortest ;)
First, based on your example
const { apply, compose, either, flip, identity, map, mergeAll, objOf, prop, replace, toPairs, useWith } = require('ramda');
const RenameKeys = f => compose(mergeAll, map(apply(useWith(objOf, [f]))), toPairs);
const originalArr = [
{
personName: 'Joe',
},
];
const keymaps = {
personName: 'name',
};
// const HowToRename = flip(prop)(keymaps); // if you don't have keys not specified in keymaps explicitly
const HowToRename = either(flip(prop)(keymaps), identity);
console.log(map(RenameKeys(HowToRename))(originalArr));
Second option, using any arbitrary lambda with renaming rules:
const { apply, compose, map, mergeAll, objOf, replace, toPairs, useWith } = require('ramda');
const RenameKeys = f => compose(mergeAll, map(apply(useWith(objOf, [f]))), toPairs);
const HowToRename = replace(/(?<=.)(?!$)/g, '_'); // for example
console.log(RenameKeys(HowToRename)({ one: 1, two: 2, three: 3 }));
Yields
{ o_n_e: 1, t_w_o: 2, t_h_r_e_e: 3 }
Third, you can use object-based rename rules from the first example and use fallback strategy, e.g. replace
like in the second example, instead of identity
.