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

时间:2017-04-24 19:25:02

标签: javascript lodash

例如,我想对Intl.Collator().compare进行排序。有没有办法让这个比较器通过_.sortBy使用?

8 个答案:

答案 0 :(得分:2)

不,不幸的是,目前可能

解决方法是使用iteratees函数将值映射到标准比较器将正确排序的值。然而,这几乎不可行。

此处还要求https://github.com/lodash/lodash/issues/246,但作者没有回复。

答案 1 :(得分:1)

你可以使用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将数组映射到一个新数组,这样它就不会修改传入其中的数组并使用native sort()方法。

答案 2 :(得分:1)

不是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

答案 3 :(得分:0)

如其他答案所述,您不能像在_.sortBy中那样将比较器传递给Array.prototype.sort()

一种解决方法是向对象添加一个新的计算属性,该属性将成为顺序,然后在其上使用_.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}]

答案 4 :(得分:0)

lodash/fp(函数式编程lodash)的简单实现,带有curring(实际上并不限于lodash):

const sortWith = comparator => list => list.map(i => i).sort(comparator);

对于TypeScript:

type ComparatorFn<T> = (a: T, b: T) => number;

const sortWith = <P>(comparator: ComparatorFn<P>) => (list: P[]): P[] => list.map(i => i).sort(comparator);

答案 5 :(得分:0)

发现了相应的问题,在此声明所提到的功能早已合并,但不幸的是尚未发布。 https://github.com/lodash/lodash/pull/3764。拥有它真是太好了

答案 6 :(得分:0)

这足以用于基于有限值的简单排序。

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"}
]

答案 7 :(得分:0)

其实迭代者可以对返回结果进行映射:

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 函数的好处是函数式编程不可变的解决方案,因为不会改变 cardsBeforeSort 数组