Frage Sortiere ein Array von Objekten nach dem String-Eigenschaftswert in JavaScript


Ich habe ein Array von JavaScript-Objekten:

var objs = [ 
    { first_nom: 'Lazslo', last_nom: 'Jamf'     },
    { first_nom: 'Pig',    last_nom: 'Bodine'   },
    { first_nom: 'Pirate', last_nom: 'Prentice' }
];

Wie kann ich sie nach dem Wert von sortieren? last_nom in JavaScript?

ich weiss Bescheid sort(a,b), aber das scheint nur auf Strings und Zahlen zu funktionieren. Muss ich meinen Objekten eine toString-Methode hinzufügen?


1815
2017-07-15 03:17


Ursprung


Antworten:


Es ist einfach genug, eine eigene Vergleichsfunktion zu schreiben:

function compare(a,b) {
  if (a.last_nom < b.last_nom)
    return -1;
  if (a.last_nom > b.last_nom)
    return 1;
  return 0;
}

objs.sort(compare);

Oder Inline (c / o Marco Demaio):

objs.sort(function(a,b) {return (a.last_nom > b.last_nom) ? 1 : ((b.last_nom > a.last_nom) ? -1 : 0);} ); 

2695
2017-07-15 03:35



Sie können auch eine dynamische Sortierfunktion erstellen, die Objekte nach ihrem übergebenen Wert sortiert:

function dynamicSort(property) {
    var sortOrder = 1;
    if(property[0] === "-") {
        sortOrder = -1;
        property = property.substr(1);
    }
    return function (a,b) {
        var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
        return result * sortOrder;
    }
}

So können Sie ein Array von Objekten wie folgt haben:

var People = [
    {Name: "Name", Surname: "Surname"},
    {Name:"AAA", Surname:"ZZZ"},
    {Name: "Name", Surname: "AAA"}
];

... und es wird funktionieren, wenn du es tust:

People.sort(dynamicSort("Name"));
People.sort(dynamicSort("Surname"));
People.sort(dynamicSort("-Surname"));

Eigentlich beantwortet das schon die Frage. Unten ist ein Teil geschrieben, weil viele Leute mich kontaktiert haben und sich darüber beschwert haben Es funktioniert nicht mit mehreren Parametern.

Mehrere Parameter

Mit der folgenden Funktion können Sie Sortierfunktionen mit mehreren Sortierparametern erstellen.

function dynamicSortMultiple() {
    /*
     * save the arguments object as it will be overwritten
     * note that arguments object is an array-like object
     * consisting of the names of the properties to sort by
     */
    var props = arguments;
    return function (obj1, obj2) {
        var i = 0, result = 0, numberOfProperties = props.length;
        /* try getting a different result from 0 (equal)
         * as long as we have extra properties to compare
         */
        while(result === 0 && i < numberOfProperties) {
            result = dynamicSort(props[i])(obj1, obj2);
            i++;
        }
        return result;
    }
}

Was würde Ihnen ermöglichen, so etwas zu tun:

People.sort(dynamicSortMultiple("Name", "-Surname"));

Hinzufügen zum Prototyp

(Die Implementierung, die gerade unten ist, ist inspiriert von Mike Rist es Antworten)

Ich würde nicht empfehlen, einen nativen Objektprototyp zu ändern, sondern nur ein Beispiel anzugeben, damit Sie ihn für Ihre eigenen Objekte implementieren können (Für die Umgebungen, die es unterstützen, können Sie auch verwenden Object.defineProperty wie im nächsten Abschnitt gezeigt, der zumindest nicht den negativen Nebeneffekt der Aufzählung hat, wie im letzten Teil beschrieben)

Prototyp-Implementierung wäre etwa so (Hier ist ein funktionierendes Beispiel):

//Don't just copy-paste this code. You will break the "for-in" loops
!function() {
    function _dynamicSortMultiple(attr) {
       /* dynamicSortMultiple function body comes here */
    }
    function _dynamicSort(property) {
        /* dynamicSort function body comes here */
    }
    Array.prototype.sortBy = function() {
        return this.sort(_dynamicSortMultiple.apply(null, arguments));
    }
}();

Der "OK" Weg, es dem Prototyp hinzuzufügen

Wenn Sie auf IE v9.0 und höher abzielen, dann verwenden Sie, wie ich bereits erwähnt habe Object.defineProperty so was (Arbeitsbeispiel):

//Won't work below IE9, but totally safe otherwise
!function() {
    function _dynamicSortMultiple(attr) {
       /* dynamicSortMultiple function body comes here */
    }
    function _dynamicSort(property) {
        /* dynamicSort function body comes here */
    }
    Object.defineProperty(Array.prototype, "sortBy", {
        enumerable: false,
        writable: true,
        value: function() {
            return this.sort(_dynamicSortMultiple.apply(null, arguments));
        }
    });
}();

Dies kann ein akzeptabler Kompromiss sein, bis die Bindeoperator kommt an.

All dieser Spaß macht es möglich:

People.sortBy("Name", "-Surname");

Sie sollten dies lesen

Wenn Sie die direkte Prototyp-Zugriffsmethode verwenden (Object.defineProperty ist in Ordnung) und anderer Code nicht überprüft hasOwnProperty, sterben die Kätzchen! Ok, um ehrlich zu sein, kein Schaden für ein Kätzchen, aber wahrscheinlich werden die Dinge kaputt gehen und jeder andere Entwickler in deinem Team wird dich hassen:

evil

Siehst du das letzte "SortBy"? Ja. Nicht cool. Verwenden Sie Object.defineProperty, wo Sie können, und lassen Sie den Array.prototype ansonsten alleine.


649
2018-01-21 15:03



Unterstrich.js

Verwenden Sie Unterstreichung, seine kleine und tolle ...

sortBy_.sortBy (Liste, Iterator, [Kontext]) Gibt eine sortierte Kopie von   Liste, in aufsteigender Reihenfolge nach den Ergebnissen der Ausführung jedes Werts geordnet   durch Iterator. Iterator kann auch der String-Name der Eigenschaft sein   nach sortieren (zB Länge).

var objs = [ 
  { first_nom: 'Lazslo',last_nom: 'Jamf' },
  { first_nom: 'Pig', last_nom: 'Bodine'  },
  { first_nom: 'Pirate', last_nom: 'Prentice' }
];

var sortedObjs = _.sortBy( objs, 'first_nom' );

155
2018-05-10 21:24



Versteh nicht, warum die Leute es so kompliziert machen:

objs.sort(function(a, b){
  return a.last_nom > b.last_nom;
});

Für strengere Motoren:

objs.sort(function(a, b){
  return a.last_nom == b.last_nom ? 0 : +(a.last_nom > b.last_nom) || -1;
});

Tauschen Sie den Operator, damit er nach umgekehrter alphabetischer Reihenfolge sortiert wird.


140
2018-01-24 19:35



In ES6 / ES2015 oder später können Sie folgendermaßen vorgehen:

objs.sort((a, b) => a.last_nom.localeCompare(b.last_nom));

136
2018-01-29 19:44



Wenn Sie doppelte Nachnamen haben, können Sie diese nach Vornamen sortieren.

obj.sort(function(a,b){
  if(a.last_nom< b.last_nom) return -1;
  if(a.last_nom >b.last_nom) return 1;
  if(a.first_nom< b.first_nom) return -1;
  if(a.first_nom >b.first_nom) return 1;
  return 0;
});

51
2017-07-15 04:03



Einfache und schnelle Lösung für dieses Problem mithilfe der Prototypvererbung:

Array.prototype.sortBy = function(p) {
  return this.slice(0).sort(function(a,b) {
    return (a[p] > b[p]) ? 1 : (a[p] < b[p]) ? -1 : 0;
  });
}

Beispiel / Verwendung

objs = [{age:44,name:'vinay'},{age:24,name:'deepak'},{age:74,name:'suresh'}];

objs.sortBy('age');
// Returns
// [{"age":24,"name":"deepak"},{"age":44,"name":"vinay"},{"age":74,"name":"suresh"}]

objs.sortBy('name');
// Returns
// [{"age":24,"name":"deepak"},{"age":74,"name":"suresh"},{"age":44,"name":"vinay"}]

Aktualisieren: Das ursprüngliche Array wird nicht mehr geändert.


38
2017-07-10 11:54



Anstatt eine benutzerdefinierte Vergleichsfunktion zu verwenden, können Sie auch einen Objekttyp mit benutzerdefinierten Objekten erstellen toString() Methode (die von der Standardvergleichsfunktion aufgerufen wird):

function Person(firstName, lastName) {
    this.firtName = firstName;
    this.lastName = lastName;
}

Person.prototype.toString = function() {
    return this.lastName + ', ' + this.firstName;
}

var persons = [ new Person('Lazslo', 'Jamf'), ...]
persons.sort();

23
2017-07-15 07:21