Javascript sortiert ein Array von Objekten nach einer booleschen Eigenschaft

76

Das eigentliche Problem finden Sie unter Bearbeiten am Ende.

Ok, ich habe dieses Szenario:

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]

Wenn ich das mache:

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

Es gibt mir Folgendes:

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

Es macht irgendwie eine Art ... aber nicht ganz ... :(

Wie sortiere ich dieses Array?

BEARBEITEN:

Wenn Sie sich fragen, warum ich nicht nur a.sort () verwendet habe, liegt das daran, dass mein tatsächliches Array aus Objekten besteht, nicht aus einem einfachen Array wie dem, das ich veröffentlicht habe. Der echte hat Elemente, die aussehen wie [{xx: true}, {xx: false}, ...]

PCoelho
quelle
Wenn ich a.map (Funktion (x) {return x? 1: 0}) mache. Sort (Funktion (a, b) {return a> b}); funktioniert auch nicht ... Ich denke, ich könnte etwas Elementares falsch machen
PCoelho
Warum müssen Sie eine benutzerdefinierte Funktion schreiben? a.sort () sollte funktionieren
Haseeb Asif
Gibt es einen Weg mit lodash
Mina Fawzy

Antworten:

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

Sie müssen 0 zurückgeben, wenn a und b denselben Wert haben, -1, wenn a wahr ist, und 1, wenn dies nicht der Fall ist.

cPu1
quelle
1
Ja du hast es :) danke! (Ich werde Ihre Antwort akzeptieren, sobald der Stackoverflow es mir erlaubt: P)
PCoelho
32
Noch kürzer: a.sort (Funktion (x, y) {return y - x});
Frambot
Das Array, das ich sortiere, ist nicht so einfach wie das, das ich gepostet habe. Überprüfen Sie meine Bearbeitung
PCoelho
2
@ JoeFrambach Kannst du erklären, wie das funktioniert oder mich auf einen Thread verweisen, der die Syntax für so etwas erklärt?
Adam Moisa
6
@AdamMoisa Joes Lösung funktioniert aufgrund von Typ-Zwang. Grundsätzlich wird die JS-Engine bemerken, dass Sie versuchen, eine mathematische Operation (Subtraktion) für booleanWerte durchzuführen , sodass sie falsein 0und truein konvertiert wird 1.
Silvestre Herrera
35

ein einfacher Weg:

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

Sie können a.reverse () nach sort () aufrufen, wenn Sie möchten, dass es anders sortiert wird.

BEARBEITEN: Bearbeitet, um die aktualisierte Frage der Sortierung eines Arrays von Objekten anstelle eines Arrays von Booleschen Werten widerzuspiegeln.

Dandavis
quelle
1
@PranavNegandhi: Was falsch ist, ist, dass ich die Frage beantwortet habe, bevor eine Bearbeitung sie neu definiert hat ...
Dandavis
1
Großartig, nur wenn Sie möchten, dass es anders sortiert wird, tauschen Sie die Stellen aund bin der Sortierfunktion aus, anstatt aufzurufen reverse().
Yulian
17

Um eine implizite Typkonvertierung zu verhindern (welche Sprachen wie TypeScript nicht mögen), können Sie Number()den Booleschen Wert explizit in eine Zahl konvertieren:

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

Oder mit Pfeilfunktionen:

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

sroes
quelle
13

Einfache Lösung:

[true, false, true, false].sort( (a,b) => b - a)
Сергей Мисник
quelle
9

Ein Array hat keine gleichen Positionen. Warum also nicht die Gleichheitsprüfung weglassen und immer entweder -1 oder 1 zurückgeben? Dieser Ansatz funktioniert gut mit TS.

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

Hinweis: Ich bin etwas besorgt darüber, wie sich dies auf Interna der Sortierfunktion auswirkt, aber es scheint den Trick zu tun.

Wenn Sie die Sortierung umkehren möchten

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

PFB die Lösung funktionierte für mich auch in 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);
Traumentwickler
quelle
1

Eine ziemlich einfache Lösung für die Vergleichsfunktion besteht darin, zu überprüfen, ob a < bdies 0 oder 1 ergibt, wenn es in eine Zahl umgewandelt wird. Wir wollen dann 0 auf -1 und 1 auf 1 abbilden. Dazu können Sie einfach mit 2 multiplizieren und dann 1 subtrahieren.

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

oder nur

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

Problem sortiert!

Wenn einer Ihrer Werte ist, werden nullsie als false ( null*2 === 0) behandelt, und jeder Wert, undefinedder zu NaN( undefined*2 === NaN) wird, sollte in beide Sortierrichtungen gültig sein.

MattCochrane
quelle
1

Ich wollte sehen, ob ich es schaffen könnte, ohne den ? :Operator zu benutzen , nur zum Spaß.

Hinweis

Dies funktioniert für alle sortierbaren Datentypen (Zeichenfolgen, Zahlen), nicht nur für rohe Boolesche Werte. Ich bin mir nicht sicher, ob dies schneller als ? :und komplizierter ist. Ich habe nur die Bedingungen satt, also ist es nur eine persönliche Präferenz.

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

Ich kann daraus eine Utility-Funktion machen und ihr einen aussagekräftigen Namen geben:

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

also dann kann ich:

  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);
toddmo
quelle
2
Beachten Sie, dass dies sortmit einer beliebigen Zahl funktioniert, nicht nur mit -1 oder 1. Daher können Sie (a, b) => Number(a > b) - 0.5eine Multiplikation vermeiden.
Xavier Stévenne
0

Ich habe Typoskriptfehler auf dem return (x.xx === y.xx) ? 0 : x ? -1 : 1;

Dies ist meine Lösung, wenn Sie nach einer booleschen Eigenschaft sortieren möchten

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;
    });
chriscrossweb
quelle