繁体   English   中英

是否可以将自定义比较器传递给 lodash 的 sortBy function?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM