I am looking to sort an array of nested object using Ramda. I have an array:
const people = [
{ name: 'Emma', data:{ age: 70 }},
{ name: 'Peter', data:{ age: 78 }},
{ name: 'Mikhail', data:{ age: 62 }},
];
I want to sort above array using Ramda. I got this but it does not work for me.
Your help will be highly appreciated.
As you want to sort by the path data.age
, you can get the prop data
from your object using R.prop
which will give you an object, and then use R.prop()
again on that object to get the age
property. To make a function which does this, you can use R.compose()
:
const byAge = R.ascend(R.compose(R.prop('age'), R.prop('data')));
const people = [
{ name: 'Emma', data:{ age: 70 }},
{ name: 'Peter', data:{ age: 78 }},
{ name: 'Mikhail', data:{ age: 62 }},
];
const peopleByYoungestFirst = R.sort(byAge, people);
console.log(peopleByYoungestFirst);
//=> [{"name":"Mikhail","data":{"age":62}},{"name":"Emma","data":{"age":70}},{"name":"Peter","data":{"age":78}}]
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js" integrity="sha256-buL0byPvI/XRDFscnSc/e0q+sLA65O9y+rbF+0O/4FE=" crossorigin="anonymous"></script>
To break down the above compose function, say you have the object obj
, which is:
obj = { name: 'Emma', data:{ age: 70 }}
Performing R.prop('data')(obj)
will give:
{ age: 70 }
As you are interested in the age
property of the returned object, you again can run R.prop('age')
on the above object:
R.prop('age')({age: 70})
This will give 70
. So above line can be written as:
R.prop('age')(R.prop('data')(obj))
^^^^^ f ^^^^^ ^^^^^^ g ^^^^^ ^ x
The issue with this function, however, is that it doesn't return a function which we can pass obj
into to get 70
out of. Currently, it takes the form of f(g(x))
, by composing it, we can get the form of (f.g)(x)
, where f.g
composes the functions f
and g
to produce a new function. To compose in Ramda, we can use R.compose()
:
R.compose(R.prop('age'), R.prop('data'))(obj)
This can be eta-reduced to remove the obj
like it is in the example.
This approach can be generalized to:
const {pipe, split, reverse, map, apply, compose, ascend} = R;
const makeSortFn = compose(ascend, pipe(split('.'), reverse, map(R.prop), apply(compose)));
const byAge = makeSortFn('data.age');
const people = [
{ name: 'Emma', data:{ age: 70 }},
{ name: 'Peter', data:{ age: 78 }},
{ name: 'Mikhail', data:{ age: 62 }},
];
const peopleByYoungestFirst = R.sort(byAge, people);
console.log(peopleByYoungestFirst);
//=> [{"name":"Mikhail","data":{"age":62}},{"name":"Emma","data":{"age":70}},{"name":"Peter","data":{"age":78}}]
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js" integrity="sha256-buL0byPvI/XRDFscnSc/e0q+sLA65O9y+rbF+0O/4FE=" crossorigin="anonymous"></script>
But instead, I would favour Ori's approach, which can be genralized much easier by splitting a string:
R.sortBy(R.path(path_str.split('.')))
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments