Reputation: 890
Here's a list of parents and I want to sort the parents by their 2nd's child's age with ramda:
[
{
name: "Alicia",
age: "43",
children: [{
name: "Billy",
age: "3"
},
{
name: "Mary",
age: "8"
},
]
},
{
name: "Felicia",
age: "60",
children: [{
name: "Adrian",
age: "4"
},
{
name: "Joseph",
age: "5"
},
]
}
]
How do I do on about it? I tried doing something along the lines of
parents.sort(
sortBy("-children.age"))
);
Upvotes: 0
Views: 1548
Reputation: 50797
The simplest solution is, I think, just to combine sortBy
with path
:
const sortBy2ndChildAge = sortBy(path(['children', 1, 'age']))
const people = [{name: "Alicia", age: "43", children: [{name: "Billy", age: "3"}, {name: "Mary", age: "8"}]}, {name: "Felicia", age: "60", children: [{name: "Adrian", age: "4"}, {name: "Joseph", age: "5"}]}]
console.log(sortBy2ndChildAge(people))
<script src="https://bundle.run/[email protected]"></script><script>
const {sortBy, path} = ramda </script>
There are several potential flaws with this, that others have noted. Are parents always guaranteed to have at least two children? Do we really want a lexicographic sort -- i.e. '11' < '2'
-- or do you want to convert these values to numbers?
It would be easy enough to fix both of these problems: sortBy(compose(Number, pathOr(0, ['children', 1, 'age'])))
, but that depends upon what you're trying to do. If you're just using this to learn about Ramda, then sortBy
and path
are both useful functions to know. sortBy
is useful when you can convert the items to be sorted to some ordered type -- Strings, numbers, dates, or anything with a numeric valueOf
method. You supply that conversion function and a list of values and it will sort by that. path
is simply a null-safe read for a list of nested properties in an object.
Upvotes: 0
Reputation: 191986
Use R.sortBy
and extract the value with a function create with R.pipe
. The function gets the children array of the object with R.prop
, takes the last child (R.last
), gets the age
with R.propOr
(returns 0 if no children), and converts to a Number
. You can use R.negate
if you want to reverse the order.
const { sortBy, pipe, prop, last, propOr } = R
const fn = sortBy(pipe(
prop('children'),
last,
propOr(0, 'age'),
Number,
// negate - if you want to reverse the order
))
const parents = [{"name":"Alicia","age":"43","children":[{"name":"Billy","age":"3"},{"name":"Mary","age":"8"}]},{"name":"Felicia","age":"60","children":[{"name":"Adrian","age":"4"},{"name":"Joseph","age":"5"}]}]
const result = fn(parents)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
Upvotes: 2
Reputation: 18901
I would use sortWith
with ascend
functions. Using sortWith
allows you to define a first sort order function, a second sort order function, etc.
const people = [
{
name: "Alicia",
age: "43",
children: [{
name: "Billy",
age: "3"
},
{
name: "Mary",
age: "8"
},
]
},
{
name: "Felicia",
age: "60",
children: [{
name: "Adrian",
age: "4"
},
{
name: "Joseph",
age: "5"
},
]
}
];
const by2ndChildAge = ascend(pathOr(0, ['children', 1, 'age']));
const by1stChildAge = ascend(pathOr(0, ['children', 0, 'age']));
console.log(sortWith([by2ndChildAge, by1stChildAge], people));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
<script>const {sortWith, ascend, pathOr} = R;</script>
Upvotes: 0
Reputation: 53598
Assuming your JSON above was hand generated, including the syntax errors, then assuming your real data is just fine (an array of parents, with each parent having a children
array of objects) then a normal JS sort will work just fine:
const compareC2(parent1, parent2) {
let c1 = parent1.children;
let c2 = parent2.children;
if (!c1 || !c2) {
// what happens if someone has no children?
}
let l1 = c1.length;
let l2 = c2.length;
if (l1 === 0 || l2 === 0) {
// different symptom, but same question as above
}
if (l1 !== l2) {
// what happens when the child counts differ?
}
if (l1 !== 2) {
// what happens when there are fewer, or more than, 2 children?
}
// after a WHOLE LOT of assumptions, sort based on
// the ages of the 2nd child for each parent.
return c1[1].age - c2[1].age;
}
let sorted = parents.sort(compareC2);
Upvotes: 0
Reputation: 1639
In vanilla JavaScript (making some assumptions about the relatively poorly formatted input) using the Array.prototype.sort
method:
let parents = [ .... ]; // What you have above
parents = parents.sort((a, b) => {
return a.children[1].age - b.children[1].age; // Change - to + for ascending / descending
});
Be careful though - what would happen if a parent had fewer than 2 children?
Upvotes: 0