Javascript sắp xếp mảng đối tượng theo thuộc tính boolean


79

Xem chỉnh sửa ở cuối cho vấn đề thực tế.

Ok, tôi có tình huống này:

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]

Sau đó, nếu tôi làm điều này:

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

Nó cho tôi điều này:

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

Nó sắp xếp một loại ... nhưng không hoàn toàn ... :(

Làm cách nào để sắp xếp mảng này?

BIÊN TẬP:

Nếu bạn đang thắc mắc tại sao tôi không chỉ sử dụng a.sort () là bởi vì mảng thực tế của tôi là các đối tượng, không phải là một mảng thuần túy như mảng tôi đã đăng. Phần tử thực có các phần tử giống như [{xx: true}, {xx: false}, ...]


Nếu tôi thực hiện a.map (function (x) {return x? 1: 0}). Sort (function (a, b) {return a> b}); không hoạt động hoặc ... Tôi nghĩ rằng tôi có thể làm điều gì đó sai tiểu học
PCoelho

tại sao bạn cần viết hàm tùy chỉnh? a.sort () nên làm việc
Haseeb Asif

là có được một cách sử dụng lodash
Mina Fawzy

Câu trả lời:


203

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);

Bạn phải trả về 0 khi a và b đều có cùng giá trị, -1 nếu a đúng và 1 nếu ngược lại.


1
Yep you got it :) cảm ơn! (Tôi sẽ chấp nhận câu trả lời của bạn càng sớm càng stackoverflow cho phép tôi: P)
PCoelho

35
Thậm chí ngắn hơn: a.sort (function (x, y) {return y - x});
Frambot

mảng mà tôi đang sắp xếp không đơn giản như mảng tôi đã đăng. Kiểm tra chỉnh sửa của tôi
PCoelho

2
@JoeFrambach Bạn có thể giải thích cách hoạt động của nó không hoặc chỉ cho tôi một chuỗi giải thích cú pháp cho một cái gì đó tương tự?
Adam Moisa

6
Giải pháp của @AdamMoisa Joe hoạt động nhờ một thứ gọi là Loại cưỡng chế. Về cơ bản, công cụ JS sẽ thông báo rằng bạn đang cố gắng thực hiện một phép toán (phép trừ) trên booleancác giá trị, vì vậy nó sẽ chuyển đổi falsethành 0truethành 1.
Silvestre Herrera,

36

một cách đơn giản hơn:

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);

bạn có thể gọi a.reverse () sau sort () nếu bạn muốn nó được sắp xếp theo cách khác ..

EDIT: được chỉnh sửa để phản ánh câu hỏi cập nhật về việc sắp xếp một mảng đối tượng thay vì một mảng boolean.


1
@PranavNegandhi: có chuyện gì vậy là tôi đã trả lời các câu hỏi trước khi chỉnh sửa lại định nghĩa nó ...
dandavis

1
Tuyệt vời, chỉ cần bạn muốn nó được sắp xếp theo cách khác, hãy hoán đổi vị trí của abtrong hàm sắp xếp, thay vì gọi reverse().
Yulian

19

Để ngăn chuyển đổi kiểu ngầm định (ngôn ngữ như TypeScript không thích), bạn có thể sử dụng Number()để chuyển đổi rõ ràng boolean thành một số:

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);

Hoặc sử dụng các hàm mũi tên:

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);


Một caveat: chức năng sắp xếp so sánh điều này sẽ không làm việc với 'giá trị undefined` trong mảng đầu vào
JabbyPanda


9

Một mảng không có bất kỳ vị trí nào bằng nhau, vậy tại sao không bỏ kiểm tra bằng và luôn trả về -1 hoặc 1. Cách tiếp cận này hoạt động tốt với TS.

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

Lưu ý: Tôi hơi lo lắng về cách điều này ảnh hưởng đến bên trong của hàm sắp xếp, nhưng nó có vẻ là một mẹo nhỏ.

Nếu bạn muốn sắp xếp ngược lại

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

1

Giải pháp PFB cũng phù hợp với tôi trong Typecript 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

Một giải pháp khá đơn giản cho hàm so sánh là kiểm tra xem a < b, điều này sẽ cho 0 hoặc 1 khi chuyển đổi thành một số. Sau đó, chúng tôi muốn ánh xạ 0 thành -1 và 1 với 1. Để làm điều đó, bạn chỉ cần nhân với 2 rồi trừ 1.

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

hoặc chỉ

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

Vấn đề đã được sắp xếp!

Nếu bất kỳ giá trị nào của bạn nullđược coi là sai ( null*2 === 0) và bất kỳ giá trị nào undefinedsẽ trở thành NaN( undefined*2 === NaN), điều này sẽ khiến nó tồn tại theo một trong hai hướng sắp xếp.


1

Tôi muốn xem liệu tôi có thể làm điều đó mà không cần sử dụng ? :nhà điều hành, chỉ cho vui.

Ghi chú

Điều này hoạt động trên tất cả các kiểu dữ liệu có thể sắp xếp (chuỗi, số), không chỉ boolean thô. Tôi không chắc liệu điều này có nhanh hơn hay không ? :và nó phức tạp hơn. Tôi phát ngán nhà có điều kiện nên đó chỉ là sở thích cá nhân.

  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);

Tôi có thể biến nó thành một hàm tiện ích và đặt cho nó một cái tên có ý nghĩa:

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

vậy thì tôi có thể:

  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
Lưu ý rằng nó sorthoạt động với bất kỳ số nào không chỉ -1 hoặc 1. Do đó bạn có thể sử dụng (a, b) => Number(a > b) - 0.5để tránh một phép nhân.
Xavier Stévenne

0

Tôi có lỗi sắp chữ trên return (x.xx === y.xx) ? 0 : x ? -1 : 1;

Đây là giải pháp của tôi khi bạn muốn sắp xếp trên thuộc tính boolean

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;
    });
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.