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}, ...]


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.


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.


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



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)

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

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.


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

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;
    });
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.