这是一份父母的名单,我想按照他们的第二个孩子的年龄和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"
},
]
}
]
我该怎么做呢?我试着做一些事情
parents.sort(
sortBy("-children.age"))
);
使用R.sortBy
并使用R.pipe
创建的函数提取值。该函数使用R.prop
获取对象的children数组,获取最后一个子项(R.last
),使用age
获取R.propOr
(如果没有子项则返回0),并转换为Number
。如果要撤销订单,可以使用R.negate
。
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>
在vanilla JavaScript中(使用Array.prototype.sort
方法对格式相对较差的输入做出一些假设):
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
});
但要小心 - 如果父母少于2个孩子会怎么样?
假设你的JSON是手动生成的,包括语法错误,那么假设你的真实数据很好(一组父项,每个父项都有一个children
对象数组),那么正常的JS排序就可以了:
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);
我会使用sortWith
与ascend
函数。使用sortWith
可以定义第一个排序顺序函数,第二个排序顺序函数等。
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>
我认为,最简单的解决方案就是将sortBy
与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>
其他人已经注意到,这有几个潜在的缺陷。父母总是保证至少有两个孩子吗?我们真的想要一个词典排序 - 即'11' < '2'
- 或者你想将这些值转换为数字?
解决这两个问题很容易:sortBy(compose(Number, pathOr(0, ['children', 1, 'age'])))
,但这取决于你想要做什么。如果您只是用它来了解Ramda,那么sortBy
和path
都是有用的功能。当你可以将要排序的项目转换为某些有序类型 - 字符串,数字,日期或任何带有数字sortBy
方法的东西时,valueOf
非常有用。您提供转换函数和值列表,它将按此排序。 path
只是一个对象的嵌套属性列表的空安全读取。