[英]How to use lodash's _sortBy() to alphabetically sort this list with a custom requirement?
[英]Is it possible to pass a custom comparator to lodash's sortBy function?
例如,我想根据Intl.Collator().compare
进行排序。 有什么方法可以将此比较器传递给_.sortBy
使用吗?
您可以使用 lodash mixin
_.mixin({
sortWith : function(arr, customFn) {
return _.map(arr).sort(customFn)
}
});
你现在可以做
_.sortWith(array, function(a, b) {
//custom function that returns either -1, 0, or 1 if a is <, ==, or > than b
});
你现在可以像这样链接:
_.chain(myObject)
.get('some_array_property')
.sortWith(function(a, b) {
//determine if a <=> b
})
.value();
在内部, sortWith 将数组映射到一个新数组,这样它就不会修改传递给它的数组并使用本机 sort()方法。
不,不幸的是这是目前不可能。
解决方法是使用iteratees
函数将值映射到标准比较器将正确排序的内容。 然而,这几乎从不实用。
这里也有人要求https://github.com/lodash/lodash/issues/246 ,但作者没有回应。
不完全确定你在找什么。 但是,如果您正在寻找在 lodash 排序中使用比较器的方法,这可能会有所帮助:
使用_.chain()
获取 lodash collect 将使您能够将比较器传递给sort()
console.log(JSON.stringify(_.sortBy(res, lat))); // sortBy doesn't take in comparator
console.log(
JSON.stringify(
_.chain(res)
.sort((a, b) => b.lat - a.lat) // sort takes in comparator
.value()
)
);
不是 lodash,但对于寻找本地排序的人来说可能会派上用场。
var customSort = ( selector, options, locales = undefined, ) => (a, b) => { return selector(a).localeCompare(selector(b), locales, {numeric: true,...options}); }; var x = [ { name: '1-test' }, { name: '01-test' }, { name: '11-test' }, { name: '11-Test' }, { name: '10-test' }, { name: '40-btest' }, { name: '40-ctest' }, { name: '40-atest' }, { name: '2-test' }, { name: '20-test' }, { name: 'ätest' }, { name: 'atest' }, ]; console.log(x.sort(customSort((x) => x.name))); console.log(x.sort(customSort((x) => x.name, { caseFirst: 'upper' }))); // in Swedish console.log(x.sort(customSort((x) => x.name, { sensitivity: 'base' },'sv')));
选项来自: https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare
正如其他答案所说,您不能像在Array.prototype.sort()
那样将比较器传递给_.sortBy
。
一种解决方法是将一个新的计算属性添加到将作为排序的对象,然后在其上使用_.sortBy
。
所以如果你有一个像[{name: "hello there"}, {name: "world"}]
这样的对象列表,但你想按名称长度对它们进行排序,你可以这样做:
_(arr)
//augment each object with a calculated `order` property
.map(obj => ({...obj, order: obj.name.length}))
.sortBy('order')
.value()
结果: [{name: "world", order: 5}, {name: "hello there", order: 11}]
带有柯里化功能的lodash/fp
(函数式编程 lodash)的简单实现(实际上不限于 lodash):
const sortWith = comparator => list => list.map(i => i).sort(comparator);
对于打字稿:
type ComparatorFn<T> = (a: T, b: T) => number;
const sortWith = <P>(comparator: ComparatorFn<P>) => (list: P[]): P[] => list.map(i => i).sort(comparator);
找到了对应的issue,这里说明提到的特性早就被合并了,可惜还没有发布。 https://github.com/lodash/lodash/pull/3764 。 如果它可用,那就太好了
这对于基于有限值的简单排序就足够了。
const MAP = {
BRONZE: 1,
SILVER: 2,
GOLD: 3,
PLATINUM: 4,
}
const DATA = [
{ name: 'A', type: 'SILVER' },
{ name: 'B', type: 'BRONZE' },
{ name: 'C', type: 'PLATINUM' },
{ name: 'F', type: 'SILVER' },
{ name: 'G', type: 'GOLD' },
{ name: 'H', type: 'BRONZE' },
]
_.sortBy(DATA, (item) => MAP[item.type])
结果:
[
{"name":"B","type":"BRONZE"},
{"name":"H","type":"BRONZE"},
{"name":"A","type":"SILVER"},
{"name":"F","type":"SILVER"},
{"name":"G","type":"GOLD"},
{"name":"C","type":"PLATINUM"}
]
实际上迭代者可以映射返回结果:
const users = [
{ 'user': 'fred', 'age': 48 },
{ 'user': 'barney', 'age': 36 },
{ 'user': 'fred', 'age': 40 },
{ 'user': 'barney', 'age': 34 }
];
_.sortBy(users, [function(o) { return o.user; }]);
// output: objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
或 iteratees 可以是普通的 js 排序函数,就像我在下面的示例中所做的那样,当cardsStatus === 'NORI'
时,对对象数组进行排序以对卡片进行排序,因此卡片应该位于数组的顶部
const cardsBeforeSort = [
{
"cardStatus": "NORM",
"consumedLimit": 0,
"cardAccountSerial": "10551880",
"cashLimit": null,
"applePayStatus": "ELIGIBLE",
"embossName": "Hdhh",
"nickName": "",
"aan": "123",
"balance": -9,
"key": "405433******8106"
},
{
"cardStatus": "NORI",
"consumedLimit": 0,
"cardAccountSerial": "10551908",
"cashLimit": null,
"applePayStatus": "ELIGIBLE",
"embossName": "Hdhh",
"nickName": "",
"aan": "123",
"balance": 1,
"key": "405433******8382"
},
{
"cardStatus": "HOLD",
"consumedLimit": -169122.81,
"cardAccountSerial": "10548192",
"cashLimit": null,
"applePayStatus": "ELIGIBLE",
"embossName": "Hdjj",
"nickName": "",
"aan": "123",
"balance": 5579.29,
"key": "417323******3321"
},
{
"cardStatus": "NORI",
"consumedLimit": -7.74,
"cardAccountSerial": "10549814",
"cashLimit": null,
"applePayStatus": "ELIGIBLE",
"embossName": "Hdhh",
"nickName": "",
"aan": "123",
"balance": 1,
"key": "429927******1548"
}
]
const sortedCards = sortBy(userCards, [
(first, second) =>
first.cardStatus === 'NORI' ? -1 : second === 'NORI' ? 1 : 0,
]);
这将导致以下输出:
console.log(sortedCards);
[
{
"cardStatus": "NORI",
"consumedLimit": -7.74,
"cardAccountSerial": "10549814",
"cashLimit": null,
"applePayStatus": "ELIGIBLE",
"embossName": "Hdhh",
"nickName": "",
"aan": "123",
"balance": 1,
"key": "429927******1548"
},
{
"cardStatus": "NORI",
"consumedLimit": 0,
"cardAccountSerial": "10551908",
"cashLimit": null,
"applePayStatus": "ELIGIBLE",
"embossName": "Hdhh",
"nickName": "",
"aan": "123",
"balance": 1,
"key": "405433******8382"
},
{
"cardStatus": "NORM",
"consumedLimit": 0,
"cardAccountSerial": "10551880",
"cashLimit": null,
"applePayStatus": "ELIGIBLE",
"embossName": "Hdhh",
"nickName": "",
"aan": "123",
"balance": -9,
"key": "405433******8106"
},
{
"cardStatus": "HOLD",
"consumedLimit": -169122.81,
"cardAccountSerial": "10548192",
"cashLimit": null,
"applePayStatus": "ELIGIBLE",
"embossName": "Hdjj",
"nickName": "",
"aan": "123",
"balance": 5579.29,
"key": "417323******3321"
},
]
实际上,使用 sortBy lodash 函数的好处是函数式编程不可变的解决方案,因为不改变cardBeforeSort数组
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.