JavaScript通过布尔属性对对象进行排序


76

有关实际问题,请参阅最后的编辑。

好的,我有这种情况:

a = [false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]

然后,如果我这样做:

a.sort(function(a,b){return !a && b});

它给了我这个:

[false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]

这有点儿排序...但不是很... :(

如何排序此数组?

编辑:

如果您想知道为什么我不只使用a.sort()是因为我的实际数组是对象,而不是我发布的简单数组。真正的元素具有看起来像[{xx:true},{xx:false},...]的元素


如果我这样做a.map(function(x){return x?1:0})。sort(function(a,b){return a> b}); 也不起作用...我想我可能在做一些基本的错误
PCoelho 2013年

为什么需要编写自定义函数?a.sort()应该起作用
Haseeb Asif

有没有一种使用lodash的方法
Mina Fawzy

Answers:


196

a = [false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false];
    
    
    a.sort(function(x, y) {
        // true values first
        return (x === y)? 0 : x? -1 : 1;
        // false values first
        // return (x === y)? 0 : x? 1 : -1;
    });
    
    console.log(a);

当a和b的值相同时,必须返回0;如果a为true,则必须返回-1,否则返回1。


1
是的,你明白了:)谢谢!(只要stackoverflow允许我接受,我就会接受您的回答:P)
PCoelho 2013年

32
甚至更短:a.sort(function(x,y){return y-x});
Frambot

我要排序的数组不像我发布的数组那么简单。检查我的编辑
PCoelho 2013年

2
@JoeFrambach您能解释一下它是如何工作的,或者可以将我指向一个解释此类语法的线程吗?
亚当·莫萨

6
@AdamMoisa Joe的解决方案之所以有效,是因为有一种类型强制(Type Coercion)。基本上,JS引擎会注意到你正在试图做一个数学运算(减)boolean值,所以它会转换false0true1
Silvestre Herrera,

35

一种更简单的方法:

a = [{xx:true},{xx:false},{xx:true},{xx:false},{xx:true},{xx:false},{xx:true},{xx:false},{xx:true},{xx:false},{xx:true},{xx:false},{xx:true},{xx:false},{xx:true},{xx:false},{xx:true},{xx:false}];

a.sort(function(a,b){return a.xx-b.xx});

console.log(a);

您可以在sort()之后调用a.reverse(),如果您希望以其他方式对其进行排序。

编辑:编辑以反映对对象数组而不是布尔数组进行排序的更新问题。


1
@PranavNegandhi:问题是我在编辑重新定义之前回答了这个问题……
dandavis

1
太好了,就算您希望它以其他方式排序,也可以交换ab在sort函数中的位置,而不是调用reverse()
浴帘

17

为了防止隐式类型转换(像TypeScript这样的语言不喜欢),可以使用Number()将布尔值显式转换为数字:

a = [false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false];
a.sort(function(x, y) {
   return Number(x) - Number(y);
});
console.log(a);

或使用箭头功能:

a = [false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false];
a.sort((x, y) => Number(x) - Number(y));
console.log(a);



9

数组没有任何相等的位置,因此为什么不放弃相等检查,而总是返回-1或1。这种方法对TS效果很好。

a.sort(x => x ? -1 : 1)

注意:我有点担心这如何影响sort函数的内部,但似乎可以解决问题。

如果要反向排序

a.sort(x => !x ? -1 : 1)

1

PFB该解决方案也适用于Typescript Angular 2,

  let a = [{aa:"1",xx:true},{aa:"10",xx:false},{aa:"2",xx:true},{aa:"11",xx:false},{aa:"3",xx:true},{aa:"12",xx:false},{aa:"4",xx:true},{aa:"13",xx:false},{aa:"5",xx:true},{aa:"14",xx:false},{aa:"6",xx:true},{aa:"15",xx:false},{aa:"7",xx:true},{aa:"16",xx:false},{aa:"8",xx:true},{aa:"17",xx:false},{aa:"9",xx:true},{aa:"18",xx:false}];

    //a.sort(function(a,b){return a.xx-b.xx});
    a.sort(function (x, y) {
        // true values first
        return (x.xx === y.xx) ? 0 : x ? -1 : 1;
        // false values first
        // return (x === y)? 0 : x? 1 : -1;
    });
    return JSON.stringify(a);

1

比较功能的一个非常简单的解决方案是检查,如果a < b将转换为数字,则给出0或1。然后,我们要映射0到-1和1到1。为此,您可以乘以2然后减去1。

data.sort(function (a, b) {
  return (a < b) * 2 - 1
}

要不就

data.sort((a, b) => (a < b) * 2 - 1)

问题排序!

如果您有任何值,null它们将被视为false(null*2 === 0),并且任何undefined将成为NaNundefined*2 === NaN)的都应使其在任一排序方向上都处于最后状态。


1

我想看看是否可以不使用 ? :操作员,只是为了好玩。

注意

这适用于所有可排序的数据类型(字符串,数字),而不仅仅是原始布尔值。我不确定这是否比? :它更快,并且更令人费解。我只是厌倦有条件的,所以这只是个人喜好。

  var b = [false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]
  .sort((a,b) => Number(a > b) * 2 - 1);

我可以将其转换为实用程序函数,并为其赋予一个有意义的名称:

  var sortOrder = {
    asc: (a,b) => Number(a > b) * 2 - 1,
    desc: (a,b) => Number(a < b) * 2 - 1
  }

这样我就可以:

  var b = [false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]
  .sort(sortOrder.asc);

2
请注意,该函数sort可用于除-1或1以外的任何数字。因此,可以使用它(a, b) => Number(a > b) - 0.5来避免乘法。
XavierStévenne

0

我在上遇到打字错误 return (x.xx === y.xx) ? 0 : x ? -1 : 1;

当您想对布尔属性进行排序时,这是我的解决方案

this.mediaList.sort( (a: MediaAutosubscriptionModel, b: MediaAutosubscriptionModel) => {
    let status1: number = a.status === StatusEnum.ACTIVE ? 1 : 0;
    let status2: number = b.status === StatusEnum.ACTIVE ? 1 : 0;
    let comparison: number = 0;
    let direction: number = this.sortDirection === SortDirectionsEnum.ASC ? -1 : 1;
    if (status1 > status2) {
        comparison = direction;
    } else if (status1 < status2) {
        comparison = -1 * direction;
    }
        return comparison;
    });
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.