首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Javascript排序自定义比较器函数-对排序的数组进行排序

Javascript排序自定义比较器函数-对排序的数组进行排序
EN

Stack Overflow用户
提问于 2011-08-23 15:27:38
回答 3查看 45.2K关注 0票数 29

我有一个以下形式的对象数组:

代码语言:javascript
复制
arr[0] = { 'item1' : 1234, 'item2' : 'a string' };

我首先根据'item1'对它进行排序,这很简单。现在,我想再次对arr (按'item1'排序)进行排序,但这次是按'item2'排序,但仅针对'item1'相同的元素。最终的数组将如下所示:

代码语言:javascript
复制
arr = [
  { 'item1' : 1234, 'item2' : 'apple' },
  { 'item1' : 1234, 'item2' : 'banana' },
  { 'item1' : 1234, 'item2' : 'custard' },
  { 'item1' : 2156, 'item2' : 'melon' },
  { 'item1' : 4345, 'item2' : 'asparagus' } 
];

我尝试为第二种情况编写一个排序函数,如下所示:

代码语言:javascript
复制
arr.sort(function(a,b){
  if(a.item1 === b.item1){
    return a.item2 > b.item2 ? 1 : a.item2 < b.item2 : -1 : 0;
  }
});

我可以在一个函数中组合这两个排序,以获得最终的排序数组,但在某些情况下,我必须仅按'item1''item2'排序。

EN

回答 3

Stack Overflow用户

发布于 2011-08-23 15:32:53

您可以使用四种不同的比较函数-一个按item1排序,一个按item2排序,一个按item1排序,然后按item2排序,另一个按item2排序,然后按item1排序。

例如:

代码语言:javascript
复制
arr.sort(function(a,b){
  if(a.item1 == b.item1){
    return a.item2 > b.item2 ? 1 : a.item2 < b.item2 ? -1 : 0;
  }

  return a.item1 > b.item1 ? 1 : -1;
});
票数 42
EN

Stack Overflow用户

发布于 2019-07-31 05:36:41

我最近也问了同样的问题。使用了与langpavel类似的解决方案,但我更喜欢将其一分为二。首先是一个链式的比较器帮助器,它允许多个排序规则,每个规则在相等的情况下作为平局断路器顺序应用:

代码语言:javascript
复制
    type Comparator<T> = (a: T, b: T) => number; // -1 | 0 | 1

    /**
     * Allow to chain multiple comparators, each one called to break equality from the previous one.
     */
    function chainedComparator<T>(...comparators: Comparator<T>[]): Comparator<T> {
        return (a: T, b: T) => {
            let order = 0;
            let i = 0;
    
            while (!order && comparators[i]) {
                order = comparators[i++](a, b);
            }
    
            return order;
        };
    }

我喜欢它,因为它接受并返回排序比较器。因此,如果你有一个其他比较器的集合,它们很容易使用。

然后你可以用一个额外的帮手来简化你的生活。这个函数根据传递给每个项目的lambda的结果返回一个排序比较器。

代码语言:javascript
复制
    type Comparable = string | number;

    /**
     * Returns a comparator which use an evaluationFunc on each item for comparison
     */
    function lambdaComparator<T>(evaluationFunc: ((item: T) => Comparable), reversed = false): Comparator<T> {
        return (a: T, b: T) => {
            const valA = evaluationFunc(a);
            const valB = evaluationFunc(b);
            let order = 0;
    
            if (valA < valB) {
                order = -1;
            } else if (valA > valB) {
                order = 1;
            }
            return reversed ? -order : order;
        };
    }

这里的reversed不需要回答这个问题,但可以很容易地颠倒顺序。

要具体回答这个问题,请使用我们的两个比较器:

代码语言:javascript
复制
    arr.sort(chainedComparator(
        lambdaComparator(a => a.item1),
        lambdaComparator(a => a.item2.toLowerCase()) // "banana" before "Melon"
    ));

因为最初的问题是纯JavaScript的,精度:如果你不习惯使用TypeScript,你只需去掉输入<T>: T: ((item: T) => Comparable) everywhere和两行type就可以得到普通的JavaScript。

票数 7
EN

Stack Overflow用户

发布于 2020-11-12 20:57:11

您可以只使用npm导入type-comparator,然后使用queue进行链接:

代码语言:javascript
复制
const comparator = queue([
    map(x => x.item1, asc),
    map(x => x.item2, asc)
]);
arr.sort(comparator);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7157590

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档