简体   繁体   English

在 JavaScript 中编写排序方法的最简洁方法,该方法对多个 object 属性进行排序

[英]Cleanest way to write a sort method in JavaScript that sorts on multiple object properties

This is a sort of code golf / code cleanliness and conciseness question.这是一种代码高尔夫/代码清洁度和简洁性问题。 I have an object I want to sort in JavaScript, and I'm wondering what the shortest and cleanest way to do this.我有一个 object 我想在 JavaScript 中排序,我想知道最短和最干净的方法是什么。

Given objest like this:给定这样的对象:

items = [
 {name: "Pierre",  boosted: true,  rank: 1   },
 {name: "Burhan",  boosted: false, rank: null},
 {name: "Ellise",  boosted: false, rank: 1   },
 {name: "Glenn",   boosted: true,  rank: 2   },
 {name: "Zidane",  boosted: false, rank: null},
 {name: "Antonia", boosted: false, rank: 2   },
];

I need to sort with these requirements:我需要按照这些要求进行排序:

  1. Boosted items first, then by name ascending within multiple boosted items.首先提升项目,然后在多个提升项目中按name升序。
  2. Next put rank , ascending, where rank.= null.接下来放rank ,升序,其中 rank.= null。 Doesn't matter how we sort if there's a tie in rank .如果rank相同,我们如何排序都没关系。
  3. When rank = null, sort by name ascending.当 rank = null 时,按name升序排序。

So essentially three buckets to sort the items by, then within each bucket sort by name.所以本质上是三个桶来对项目进行排序,然后在每个桶中按名称排序。 Rank isn't normalized, it can be any valid number.排名未标准化,它可以是任何有效数字。

The resulting list above sorted should look like this:上面排序的结果列表应如下所示:

sorted = [
 {name: "Glenn",   boosted: true,  rank: 2   },
 {name: "Pierre",  boosted: true,  rank: 1   },
 {name: "Ellise",  boosted: false, rank: 1   },
 {name: "Antonia", boosted: false, rank: 2   },
 {name: "Burhan",  boosted: false, rank: null},
 {name: "Zidane",  boosted: false, rank: null},
];

I wrote this long method:我写了这个长方法:

items.sort((a, b) => {
    // Boosted
    if (a.boosted && b.boosted) {
        return a.name.localeCompare(b.name);
    } else if (a.boosted && !b.boosted) {
        return -1;
    } else if (!a.boosted && b.boosted) {
        return 1;
    }

    // Ranked
    if (a.rank != null && b.rank != null) {
        return a - b;
    } else if (a.rank != null && b.rank == null) {
        return -1;
    } else if (a.rank == null && b.rank != null) {
        return 1;
    }

    // Default by name
    return a.name.localeCompare(b.name);
});

It works, but I think there are much better ways to do this, and I'm curious what styles other people recommend.它有效,但我认为有更好的方法可以做到这一点,我很好奇其他人推荐的 styles 是什么。 What's the shortest solution I could write?我能写的最短的解决方案是什么? What's the cleanest?什么最干净? What's the fastest?什么是最快的? (Since the sort method could get called many times during a sort operation) (因为在排序操作期间可能会多次调用 sort 方法)

You can use - on booleans and numbers.您可以在布尔值和数字上使用- You can use ||您可以使用|| to chain multiple sort criteria, short-circuiting when the first doesn't return 0 .链接多个排序标准,当第一个不返回0时短路。

In your case that might be在你的情况下,这可能是

items.sort((a, b) =>
  b.boosted - a.boosted ||
  (a.rank == null) - (b.rank == null) ||
  a.rank - b.rank ||
  a.name.localeCompare(b.name)
);

if you were just to sort by differently priotised columns.如果您只是按不同的优先列进行排序。 However, you've got the special requirement that boosted items should be sorted differently than non-boosted items, so you indeed need a conditional statement thrown in:但是,您有特殊要求,提升项目的排序方式应不同于非提升项目,因此您确实需要一个条件语句:

items.sort((a, b) =>
  b.boosted - a.boosted ||
  (a.boosted
    ? a.name.localeCompare(b.name)
    : (a.rank == null) - (b.rank == null) ||
      (a.rank != null
        ? a.rank - b.rank
        : a.name.localeCompare(b.name)
      )
  )
);

Personally I do this way:我个人是这样做的:

 const items = [ {name: "Pierre", boosted: true, rank: 1 }, {name: "Burhan", boosted: false, rank: null}, {name: "Ellise", boosted: false, rank: 1 }, {name: "Glenn", boosted: true, rank: 2 }, {name: "Zidane", boosted: false, rank: null}, {name: "Antonia", boosted: false, rank: 2 }, ]; const gKey=({name,boosted,rank})=>`${boosted?0:1}_${(rank?=null).('000'+rank):slice(-3).'999'}_${name}` items,sort((ab)=>gKey(a):localeCompare(gKey(b)) ) // proof. items.forEach(e=>console.log(JSON,stringify(e),' (key->',gKey(e),')'))
 .as-console-wrapper { max-height: 100%;important: top; 0; }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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