4000 Stimmen

Array von Objekten nach String-Eigenschaftswert sortieren

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 last_nom in JavaScript?

Ich weiß von sort(a,b) aber das scheint nur bei Strings und Zahlen zu funktionieren. Muss ich ein toString() Methode für meine Objekte?

8 Stimmen

Mit diesem Skript können Sie genau das tun, es sei denn, Sie möchten Ihre eigene Vergleichsfunktion oder Ihren eigenen Sortierer schreiben: thomasfrank.se/sortierung_der-dinge.html

0 Stimmen

Der schnellste Weg ist die Verwendung der isomorphen sort-array Modul, das nativ sowohl im Browser als auch im Node funktioniert und jede Art von Eingabe, berechnete Felder und benutzerdefinierte Sortierreihenfolgen unterstützt.

0 Stimmen

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

30voto

JavaScript verwenden sort Methode

El sort Methode kann geändert werden, um alles zu sortieren, z. B. ein Array von Zahlen, Zeichenketten und sogar Objekte mit einer Vergleichsfunktion.

Eine Vergleichsfunktion wird als optionales Argument zur Sortiermethode.

Diese Vergleichsfunktion nimmt 2 Argumente entgegen, die im Allgemeinen a y b . Auf der Grundlage dieser beiden Argumente können Sie die Sortiermethode Ihren Wünschen entsprechend anpassen.

  1. Wenn die Vergleichsfunktion weniger als 0 zurückgibt, dann wird die sort() Methode sortiert a mit einem niedrigeren Index als b . Einfach a wird vor b kommen.
  2. Wenn die Vergleichsfunktion den Wert 0 zurückgibt, dann ist die sort() Methode lässt die Elementpositionen so, wie sie sind.
  3. Wenn die Vergleichsfunktion einen Wert größer als 0 zurückgibt, dann wird die sort() Methode sortiert a mit größerem Index als b . Einfach a wird kommen nach b .

Wenden Sie das obige Konzept auf Ihr Objekt an, wenn a wird Ihre Objekteigenschaft sein.

var objs = [
  { first_nom: 'Lazslo', last_nom: 'Jamf' },
  { first_nom: 'Pig', last_nom: 'Bodine' },
  { first_nom: 'Pirate', last_nom: 'Prentice' }
];
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);
console.log(objs)
// for better look use console.table(objs)

output

29voto

Jamie Mason Punkte 3904

Beispiel für die Verwendung:

objs.sort(sortBy('last_nom'));

Drehbuch:

/**
 * @description
 * Returns a function which will sort an
 * array of objects by the given key.
 *
 * @param  {String}  key
 * @param  {Boolean} reverse
 * @return {Function}
 */
const sortBy = (key, reverse) => {

  // Move smaller items towards the front
  // or back of the array depending on if
  // we want to sort the array in reverse
  // order or not.
  const moveSmaller = reverse ? 1 : -1;

  // Move larger items towards the front
  // or back of the array depending on if
  // we want to sort the array in reverse
  // order or not.
  const moveLarger = reverse ? -1 : 1;

  /**
   * @param  {*} a
   * @param  {*} b
   * @return {Number}
   */
  return (a, b) => {
    if (a[key] < b[key]) {
      return moveSmaller;
    }
    if (a[key] > b[key]) {
      return moveLarger;
    }
    return 0;
  };
};

0 Stimmen

Vielen Dank für die Aufschlüsselung, ich versuche zu verstehen, warum die Ziffern 1, 0, -1 werden für die Sortierung verwendet. Selbst mit Ihrer obigen Erklärung, die sehr gut aussieht, verstehe ich es immer noch nicht ganz. Ich denke immer an -1 wie bei der Verwendung der Eigenschaft Array-Länge, d.h.: arr.length = -1 bedeutet, dass der Artikel nicht gefunden wurde. Wahrscheinlich bringe ich hier etwas durcheinander, aber könnten Sie mir helfen zu verstehen, warum Ziffern 1, 0, -1 verwendet werden, um die Reihenfolge zu bestimmen? Danke.

1 Stimmen

Das ist nicht vollständig Die Funktion, die an array.sort übergeben wird, wird für jedes Element im Array einmal aufgerufen, und zwar als Argument mit dem Namen "a". Der Rückgabewert jedes Funktionsaufrufs gibt an, wie der Index (aktuelle Positionsnummer) des Elements "a" im Vergleich zum nächsten Element "b" geändert werden soll. Der Index bestimmt die Reihenfolge im Array (0, 1, 2 usw.) Wenn also "a" bei Index 5 steht und Sie -1 zurückgeben, dann ist 5 + -1 == 4 (es wird näher nach vorne verschoben) 5 + 0 == 5 (es bleibt, wo es ist) usw. Das Programm durchläuft das Array und vergleicht jedes Mal 2 Nachbarn, bis es das Ende erreicht und ein sortiertes Array zurücklässt.

1 Stimmen

Danke, dass Sie sich die Zeit genommen haben, dies näher zu erläutern. Anhand Ihrer Erklärung und der MDN Array.prototype.sort Ich werde Ihnen sagen, was ich davon halte: Im Vergleich zu a y b wenn a größer ist als b addiert 1 zum Index von a und platzieren Sie es hinter b wenn a ist kleiner als b subtrahieren Sie 1 von a und stellen Sie es vor die b . Wenn a y b gleich sind, addieren Sie 0 zu a und lassen Sie ihn dort, wo er ist.

26voto

artem Punkte 327

Warum schreiben Sie keinen kurzen Code?

objs.sort((a, b) => a.last_nom > b.last_nom ? 1 : -1)

1 Stimmen

Was ist, wenn die Werte gleich sind? Wenn es 3 Werte gibt, die Sie zurückgeben können - 1, -1, 0

0 Stimmen

@SomeoneSpecial Na und? Das Ergebnis wird das gleiche sein

0 Stimmen

Was bedeutet 1 || -1?

18voto

Sortieren von (mehr) komplexen Arrays von Objekten

Da Sie wahrscheinlich auf komplexere Datenstrukturen wie dieses Array stoßen, würde ich die Lösung erweitern.

TL;DR

Sind mehr steckbare Version basierend auf @ege-Özcan ist sehr schön 回答 .

Problema

Ich bin auf das folgende Problem gestoßen und konnte es nicht ändern. Ich wollte auch nicht, um das Objekt vorübergehend zu glätten. Auch wollte ich nicht underscore / lodash verwenden, vor allem aus Gründen der Leistung und der Spaß, es selbst zu implementieren.

var People = [
   {Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"},
   {Name: {name: "AAA", surname: "ZZZ"}, Middlename:"Abrams"},
   {Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"}
];

Ziel

Das Ziel ist es, sie in erster Linie zu sortieren nach People.Name.name und in zweiter Linie durch People.Name.surname

Hindernisse

In der Basislösung wird nun die Klammerschreibweise verwendet, um die Eigenschaften zu berechnen, nach denen dynamisch sortiert werden soll. Hier müssten wir jedoch die Klammerschreibweise ebenfalls dynamisch konstruieren, da Sie etwas wie People['Name.name'] funktionieren würde - was nicht der Fall ist.

Einfach tun People['Name']['name'] ist dagegen statisch und erlaubt nur die Abwärtsbewegung auf der n -Stufe.

Lösung

Der Hauptzusatz besteht hier darin, den Objektbaum abwärts zu gehen und den Wert des letzten Blattes, das Sie angeben müssen, sowie jedes dazwischenliegende Blatt zu bestimmen.

var People = [
   {Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"},
   {Name: {name: "AAA", surname: "ZZZ"}, Middlename:"Abrams"},
   {Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"}
];

People.sort(dynamicMultiSort(['Name','name'], ['Name', '-surname']));
// Results in...
// [ { Name: { name: 'AAA', surname: 'ZZZ' }, Middlename: 'Abrams' },
//   { Name: { name: 'Name', surname: 'Surname' }, Middlename: 'JJ' },
//   { Name: { name: 'Name', surname: 'AAA' }, Middlename: 'Wars' } ]

// same logic as above, but strong deviation for dynamic properties 
function dynamicSort(properties) {
  var sortOrder = 1;
  // determine sort order by checking sign of last element of array
  if(properties[properties.length - 1][0] === "-") {
    sortOrder = -1;
    // Chop off sign
    properties[properties.length - 1] = properties[properties.length - 1].substr(1);
  }
  return function (a,b) {
    propertyOfA = recurseObjProp(a, properties)
    propertyOfB = recurseObjProp(b, properties)
    var result = (propertyOfA < propertyOfB) ? -1 : (propertyOfA > propertyOfB) ? 1 : 0;
    return result * sortOrder;
  };
}

/**
 * Takes an object and recurses down the tree to a target leaf and returns it value
 * @param  {Object} root - Object to be traversed.
 * @param  {Array} leafs - Array of downwards traversal. To access the value: {parent:{ child: 'value'}} -> ['parent','child']
 * @param  {Number} index - Must not be set, since it is implicit.
 * @return {String|Number}       The property, which is to be compared by sort.
 */
function recurseObjProp(root, leafs, index) {
  index ? index : index = 0
  var upper = root
  // walk down one level
  lower = upper[leafs[index]]
  // Check if last leaf has been hit by having gone one step too far.
  // If so, return result from last step.
  if (!lower) {
    return upper
  }
  // Else: recurse!
  index++
  // HINT: Bug was here, for not explicitly returning function
  // https://stackoverflow.com/a/17528613/3580261
  return recurseObjProp(lower, leafs, index)
}

/**
 * Multi-sort your array by a set of properties
 * @param {...Array} Arrays to access values in the form of: {parent:{ child: 'value'}} -> ['parent','child']
 * @return {Number} Number - number for sort algorithm
 */
function dynamicMultiSort() {
  var args = Array.prototype.slice.call(arguments); // slight deviation to base

  return function (a, b) {
    var i = 0, result = 0, numberOfProperties = args.length;
    // REVIEW: slightly verbose; maybe no way around because of `.sort`-'s nature
    // Consider: `.forEach()`
    while(result === 0 && i < numberOfProperties) {
      result = dynamicSort(args[i])(a, b);
      i++;
    }
    return result;
  }
}

Beispiel

Arbeitsbeispiel auf JSBin

3 Stimmen

Warum? Dies ist nicht die Antwort auf die ursprüngliche Frage und "das Ziel" könnte einfach mit People.sort((a,b)=>{ return a.Name.name.localeCompare(b.Name.name) || a.Name.surname.localeCompare(b.Name.surname) }) gelöst werden

16voto

Mike R Punkte 163

Kombiniert man die dynamische Lösung von Ege mit der Idee von Vinay, erhält man eine schöne robuste Lösung:

Array.prototype.sortBy = function() {
    function _sortByAttr(attr) {
        var sortOrder = 1;
        if (attr[0] == "-") {
            sortOrder = -1;
            attr = attr.substr(1);
        }
        return function(a, b) {
            var result = (a[attr] < b[attr]) ? -1 : (a[attr] > b[attr]) ? 1 : 0;
            return result * sortOrder;
        }
    }
    function _getSortFunc() {
        if (arguments.length == 0) {
            throw "Zero length arguments not allowed for Array.sortBy()";
        }
        var args = arguments;
        return function(a, b) {
            for (var result = 0, i = 0; result == 0 && i < args.length; i++) {
                result = _sortByAttr(args[i])(a, b);
            }
            return result;
        }
    }
    return this.sort(_getSortFunc.apply(null, arguments));
}

Verwendung:

// Utility for printing objects
Array.prototype.print = function(title) {
    console.log("************************************************************************");
    console.log("**** "+title);
    console.log("************************************************************************");
    for (var i = 0; i < this.length; i++) {
        console.log("Name: "+this[i].FirstName, this[i].LastName, "Age: "+this[i].Age);
    }
}

// Setup sample data
var arrObj = [
    {FirstName: "Zach", LastName: "Emergency", Age: 35},
    {FirstName: "Nancy", LastName: "Nurse", Age: 27},
    {FirstName: "Ethel", LastName: "Emergency", Age: 42},
    {FirstName: "Nina", LastName: "Nurse", Age: 48},
    {FirstName: "Anthony", LastName: "Emergency", Age: 44},
    {FirstName: "Nina", LastName: "Nurse", Age: 32},
    {FirstName: "Ed", LastName: "Emergency", Age: 28},
    {FirstName: "Peter", LastName: "Physician", Age: 58},
    {FirstName: "Al", LastName: "Emergency", Age: 51},
    {FirstName: "Ruth", LastName: "Registration", Age: 62},
    {FirstName: "Ed", LastName: "Emergency", Age: 38},
    {FirstName: "Tammy", LastName: "Triage", Age: 29},
    {FirstName: "Alan", LastName: "Emergency", Age: 60},
    {FirstName: "Nina", LastName: "Nurse", Age: 54}
];

//Unit Tests
arrObj.sortBy("LastName").print("LastName Ascending");
arrObj.sortBy("-LastName").print("LastName Descending");
arrObj.sortBy("LastName", "FirstName", "-Age").print("LastName Ascending, FirstName Ascending, Age Descending");
arrObj.sortBy("-FirstName", "Age").print("FirstName Descending, Age Ascending");
arrObj.sortBy("-Age").print("Age Descending");

1 Stimmen

Vielen Dank für diese Idee! Übrigens, bitte ermutigen Sie niemanden, den Array-Prototyp zu ändern (siehe die Warnung am Ende meines Beispiels).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X