javascript zahlen Sortiere das Array von Objekten nach dem Stringwert




javascript zahlen sortieren (20)

Ich habe eine Reihe 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 in JavaScript nach dem Wert von last_nom sortieren?

Ich kenne die sort(a,b) , aber das scheint nur bei Strings und Zahlen zu funktionieren. Muss ich meinen Objekten eine toString() Methode hinzufügen?

https://code.i-harness.com


Sortieren (mehr) komplexer 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 Versionen basierend auf @ege-Özcan sehr schöner answer .

Problem

Ich traf das Unten und konnte es nicht ändern. Ich wollte das Objekt auch nicht vorübergehend abflachen. Ich wollte auch nicht Unterstrich / lodash verwenden, hauptsächlich aus Gründen der Performance und des Spaßes, 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"}
];

Tor

Das Ziel ist, es hauptsächlich nach People.Name.name und sekundär nach People.Name.surname

Hindernisse

In der Basislösung werden die Eigenschaften für die Sortierung mithilfe der Klammer-Notation berechnet. Hier müssten wir die Klammernotation jedoch auch dynamisch konstruieren, da man davon ausgehen würde, dass einige wie People['Name.name'] funktionieren würden - was nicht der Fall ist.

Auf der anderen Seite ist es einfach statisch, People['Name']['name'] tun, und Sie können nur die n- te Ebene wechseln.

Lösung

Der wichtigste Zusatz hier ist, den Objektbaum zu durchlaufen und den Wert des letzten Blatts, das Sie angeben müssen, sowie jedes Zwischenblatt festzulegen.

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://.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 zu JSBin


Ab 2018 gibt es eine viel kürzere und elegantere Lösung. Benutz einfach. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… .

Beispiel:

var items = [
  { name: 'Edward', value: 21 },
  { name: 'Sharpe', value: 37 },
  { name: 'And', value: 45 },
  { name: 'The', value: -12 },
  { name: 'Magnetic', value: 13 },
  { name: 'Zeros', value: 37 }
];

// sort by value
items.sort(function (a, b) {
  return a.value - b.value;
});

Durch die Kombination der dynamischen Lösung von Ege mit der Idee von Vinay erhalten Sie 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));
}

Verwendungszweck:

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

Ein einfacher Weg:

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

'.toLowerCase()' Sie, dass '.toLowerCase()' notwendig ist, um Fehler beim Vergleichen von Strings zu verhindern.


Einfache und schnelle Lösung für dieses Problem mithilfe der Vererbung von Prototypen:

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"}]

Update: Ändert das ursprüngliche Array nicht mehr.


Es gibt viele gute Antworten, aber ich möchte darauf hinweisen, dass sie sehr einfach erweitert werden können, um eine viel komplexere Sortierung zu erreichen. Das einzige, was Sie tun müssen, ist, den OR-Operator zu verwenden, um Vergleichsfunktionen wie folgt zu verketten:

objs.sort((a,b)=> fn1(a,b) || fn2(a,b) || fn3(a,b) )

Dabei sind fn1 , fn2 , ... die fn2 , die [-1,0,1] zurückgeben. Dies führt zu "Sorting by fn1", "sorting by fn2", was mit ORDER BY in SQL ziemlich gleich ist.

Diese Lösung basiert auf dem Verhalten von || Operator, der den ersten bewerteten Ausdruck auswertet, der in true konvertiert werden kann .

Die einfachste Form hat nur eine eingebettete Funktion wie diese:

// ORDER BY last_nom
objs.sort((a,b)=> a.last_nom.localeCompare(b.last_nom) )

Nach zwei Schritten mit last_nom first_nom Sortierreihenfolge von last_nom first_nom aussehen:

// ORDER_BY last_nom, first_nom
objs.sort((a,b)=> a.last_nom.localeCompare(b.last_nom) || 
                  a.first_nom.localeCompare(b.first_nom)  )

Eine generische Vergleichsfunktion könnte etwa so aussehen:

// ORDER BY <n>
let cmp = (a,b,n)=>a[n].localeCompare(b[n])

Diese Funktion kann erweitert werden, um numerische Felder, Groß- und Kleinschreibung, willkürliche Datentypen usw. zu unterstützen.

Sie können sie verwenden, um sie nach Sortierpriorität zu ketten:

// ORDER_BY last_nom, first_nom
objs.sort((a,b)=> cmp(a,b, "last_nom") || cmp(a,b, "first_nom") )
// ORDER_BY last_nom, first_nom DESC
objs.sort((a,b)=> cmp(a,b, "last_nom") || -cmp(a,b, "first_nom") )
// ORDER_BY last_nom DESC, first_nom DESC
objs.sort((a,b)=> -cmp(a,b, "last_nom") || -cmp(a,b, "first_nom") )

Der springende Punkt hierbei ist, dass reines JavaScript mit funktionalem Ansatz ohne externe Bibliotheken oder komplexen Code einen langen Weg zurücklegen kann. Es ist auch sehr effektiv, da kein String-Parsing durchgeführt werden muss


Ich habe einen Code, der für mich funktioniert:

arr.sort((a, b) => a.name > b.name)

UPDATE: Funktioniert nicht immer, daher ist es nicht korrekt :(


Ich weiß, dass diese Frage zu alt ist, aber ich habe keine ähnliche Implementierung wie ich gesehen.
Diese Version basiert auf der Schwartzschen Transformationssprache .

function sortByAttribute(array, ...attrs) {
  // generate an array of predicate-objects contains
  // property getter, and descending indicator
  let predicates = attrs.map(pred => {
    let descending = pred.charAt(0) === '-' ? -1 : 1;
    pred = pred.replace(/^-/, '');
    return {
      getter: o => o[pred],
      descend: descending
    };
  });
  // schwartzian transform idiom implementation. aka: "decorate-sort-undecorate"
  return array.map(item => {
    return {
      src: item,
      compareValues: predicates.map(predicate => predicate.getter(item))
    };
  })
  .sort((o1, o2) => {
    let i = -1, result = 0;
    while (++i < predicates.length) {
      if (o1.compareValues[i] < o2.compareValues[i]) result = -1;
      if (o1.compareValues[i] > o2.compareValues[i]) result = 1;
      if (result *= predicates[i].descend) break;
    }
    return result;
  })
  .map(item => item.src);
}

Hier ist ein Beispiel, wie man es benutzt:

let games = [
  { name: 'Pako',              rating: 4.21 },
  { name: 'Hill Climb Racing', rating: 3.88 },
  { name: 'Angry Birds Space', rating: 3.88 },
  { name: 'Badland',           rating: 4.33 }
];

// sort by one attribute
console.log(sortByAttribute(games, 'name'));
// sort by mupltiple attributes
console.log(sortByAttribute(games, '-rating', 'name'));

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 Sie:

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

Das beantwortet eigentlich schon die Frage. Der folgende Teil ist geschrieben, weil sich viele Leute mit mir in Verbindung gesetzt haben und sich beschwert haben, dass es nicht mit mehreren Parametern funktioniert .

Mehrere Parameter

Sie können die Funktion unten verwenden, um Sortierfunktionen mit mehreren Sortierparametern zu generieren.

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

Damit könnten Sie so etwas tun:

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

Hinzufügen zum Prototyp

(Die Implementierung, die sich gerade darunter befindet, ist von Mike Rs answer inspiriert.)

Ich würde nicht empfehlen, einen nativen Objektprototyp zu ändern, aber nur um ein Beispiel zu geben, damit Sie es in Ihre eigenen Objekte implementieren können. (Für die Umgebungen, die es unterstützen, können Sie auch Object.defineProperty wie im nächsten Abschnitt gezeigt hat nicht den negativen Nebeneffekt des Aufzählens, wie im letzten Teil beschrieben)

Die Implementierung eines Prototyps würde etwa wie folgt aussehen ( hier ein Arbeitsbeispiel ):

//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 Prototypen hinzuzufügen

Wenn Sie auf IE ab Object.defineProperty , verwenden Object.defineProperty wie bereits erwähnt, Object.defineProperty wie Object.defineProperty ( 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 der Bindungsoperator eintrifft.

Der ganze Prototypspaß ermöglicht dies:

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

Sie sollten dies lesen

Wenn Sie die direkte Prototypzugriffsmethode verwenden (Object.defineProperty ist in Ordnung) und anderer Code hasOwnProperty nicht überprüft, sterben hasOwnProperty ! Ok, um ehrlich zu sein, es kommt keinem Kätzchen wirklich etwas an, aber wahrscheinlich werden die Dinge kaputt gehen und jeder andere Entwickler in Ihrem Team wird Sie hassen:

Sehen Sie das letzte "SortBy"? Ja. Uncool. Verwenden Sie Object.defineProperty, wo Sie können, und lassen Sie den Array.prototype ansonsten stehen.


Verstehe 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 aus, um ihn in umgekehrter alphabetischer Reihenfolge sortieren zu lassen.


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

zusätzliche Parameter zum Ege-Özcan- Code

function dynamicSort(property, desc) {
    if (desc) {
        return function (a, b) {
            return (a[property] > b[property]) ? -1 : (a[property] < b[property]) ? 1 : 0;
        }   
    }
    return function (a, b) {
        return (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
    }
}

Lodash.js (Obermenge von Underscore.js )

Es ist gut, kein Framework für jedes einfache Element der Logik hinzuzufügen, aber es ist keine Schande, sich auf ein bewährtes Framework zu verlassen, die Entwicklung zu beschleunigen und die Anzahl der Fehler zu reduzieren.

Lodash produziert sehr sauberen Code und fördert einen funktionalen Programmierstil , der zu weniger Fehlern führt. Auf einen Blick wird klar, was die Absicht ist, wenn der Code ist.

Das Problem von OP kann einfach gelöst werden als:

const sortedObjs = _.sortBy(objs, 'last_nom');

Mehr Info? Wir haben zB folgendes verschachteltes Objekt:

const users = [
  { 'user': {'name':'fred', 'age': 48}},
  { 'user': {'name':'barney', 'age': 36 }},
  { 'user': {'name':'wilma'}},
  { 'user': {'name':'betty', 'age': 32}}
];

Wir können jetzt die _.property user.age , um den Pfad zu der Eigenschaft anzugeben, die abgeglichen werden soll. Wir sortieren die Benutzerobjekte nach der verschachtelten Age-Eigenschaft. Ja, es ermöglicht das Verschachteln von Eigenschaften!

const sortedObjs = _.sortBy(users, ['user.age']);

Willst du es umgekehrt? Kein Problem. Verwenden Sie _.reverse .

const sortedObjs = _.reverse(_.sortBy(users, ['user.age']));

Möchten Sie beides mit Chaining kombinieren?

const sortedObjs = _.chain(users).sortBy('user.age').reverse().value();

Eine einfache Funktion, mit der ein Objektarray nach einer Eigenschaft sortiert wird

function sortArray(array, property, direction) {
    direction = direction || 1;
    array.sort(function compare(a, b) {
        let comparison = 0;
        if (a[property] > b[property]) {
            comparison = 1 * direction;
        } else if (a[property] < b[property]) {
            comparison = -1 * direction;
        }
        return comparison;
    });
    return array; // Chainable
}

Verwendungszweck:

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

sortArray(objs, "last_nom"); // Asc
sortArray(objs, "last_nom", -1); // Desc

Mit Ramda,

npm installieren ramda

import R from 'ramda'
var objs = [ 
    { first_nom: 'Lazslo', last_nom: 'Jamf'     },
    { first_nom: 'Pig',    last_nom: 'Bodine'   },
    { first_nom: 'Pirate', last_nom: 'Prentice' }
];
var ascendingSortedObjs = R.sortBy(R.prop('last_nom'), objs)
var descendingSortedObjs = R.reverse(ascendingSortedObjs)

Sie können verwenden

Einfachster Weg: Lodash

( https://lodash.com/docs/4.17.10#orderBy )

Diese Methode ist wie _.sortBy, außer dass die Sortierreihenfolge der Iteraten angegeben werden kann. Wenn Aufträge nicht angegeben sind, werden alle Werte aufsteigend sortiert. Andernfalls geben Sie eine Reihenfolge von "desc" für absteigend oder "asc" für aufsteigende Sortierreihenfolge der entsprechenden Werte an.

Argumente

collection (Array | Object): Die zu iterierende Sammlung. [iteratees = [_. identity]] (Array [] | Funktion [] | Object [] | string []): Die Iteratees, nach denen sortiert werden soll. [order] (string []): Die Sortierreihenfolge der Iteraten.

Kehrt zurück

(Array): Gibt das neue sortierte Array zurück.

var _ = require('lodash');
var homes = [
    {"h_id":"3",
     "city":"Dallas",
     "state":"TX",
     "zip":"75201",
     "price":"162500"},
    {"h_id":"4",
     "city":"Bevery Hills",
     "state":"CA",
     "zip":"90210",
     "price":"319250"},
    {"h_id":"6",
     "city":"Dallas",
     "state":"TX",
     "zip":"75000",
     "price":"556699"},
    {"h_id":"5",
     "city":"New York",
     "state":"NY",
     "zip":"00010",
     "price":"962500"}
    ];

_.orderBy(homes, ['city', 'state', 'zip'], ['asc', 'desc', 'asc']);

Dies ist ein einfaches Problem. Ich weiß nicht, warum die Leute eine so komplexe Lösung haben.
Eine einfache Sortierfunktion (basierend auf einem schnellen Sortieralgorithmus):

function sortObjectsArray(objectsArray, sortKey)
        {
            // Quick Sort:
            var retVal;

            if (1 < objectsArray.length)
            {
                var pivotIndex = Math.floor((objectsArray.length - 1) / 2);  // middle index
                var pivotItem = objectsArray[pivotIndex];                    // value in the middle index
                var less = [], more = [];

                objectsArray.splice(pivotIndex, 1);                          // remove the item in the pivot position
                objectsArray.forEach(function(value, index, array)
                {
                    value[sortKey] <= pivotItem[sortKey] ?                   // compare the 'sortKey' proiperty
                        less.push(value) :
                        more.push(value) ;
                });

                retVal = sortObjectsArray(less, sortKey).concat([pivotItem], sortObjectsArray(more, sortKey));
            }
            else
            {
                retVal = objectsArray;
            }

            return retVal;
        }

Beispiel verwenden:

var myArr = 
        [
            { val: 'x', idx: 3 },
            { val: 'y', idx: 2 },
            { val: 'z', idx: 5 },
        ];
myArr = sortObjectsArray(myArr, 'idx');

Ich habe nicht diese besondere Ansatz gesehen vorgeschlagen, so ist hier eine lapidare Vergleich Methode , die ich verwenden möchte , die für beide funktioniert stringund number:

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

const sortBy = fn => (a, b) => -(fn(a) < fn(b)) || +(fn(a) > fn(b))
const getLastName = o => o.last_nom
const sortByLastName = sortBy(getLastName)

objs.sort(sortByLastName)
console.log(objs.map(getLastName))

Hier ist eine Erklärung von sortBy():

sortBy()akzeptiert ein fn, das den Wert aus einem Objekt auswählt, der als Vergleich verwendet werden soll, und gibt eine Funktion zurück, an die direkt übergeben werden kann Array.prototype.sort(). In diesem Beispiel verwenden wir o.last_nomals Vergleichswert. Wenn wir also zwei Objekte empfangen, Array.prototype.sort()z

{ first_nom: 'Lazslo', last_nom: 'Jamf' }

und

{ first_nom: 'Pig', last_nom: 'Bodine' }

wir gebrauchen

(a, b) => -(fn(a) < fn(b)) || +(fn(a) > fn(b))

um sie zu vergleichen.

In Erinnerung daran fn = o => o.last_nomkönnen wir die Vergleichsfunktion auf das Äquivalent erweitern

(a, b) => -(a.last_nom < b.last_nom) || +(a.last_nom > b.last_nom)

Der logische ODER- ||Operator verfügt über eine Kurzschlussfunktion, die hier sehr nützlich ist. Aufgrund seiner Funktionsweise bedeutet der Körper der obigen Funktion

if (a.last_nom < b.last_nom) return -1
return +(a.last_nom > b.last_nom)

Wenn a < bwir also zurückkehren -1, andernfalls, wenn a > bwir zurückkehren +1, aber wenn a == b, dann a < bund a > bfalsch, so kehrt es zurück +0.

Als Zusatzbonus gibt es hier in ECMAScript 5.1 das Äquivalent ohne Pfeilfunktionen, was leider nicht so knapp ist:

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

var sortBy = function (fn) {
  return function (a, b) {
    return -(fn(a) < fn(b)) || +(fn(a) > fn(b))
  }
}

var getLastName = function (o) { return o.last_nom }
var sortByLastName = sortBy(getLastName)

objs.sort(sortByLastName)
console.log(objs.map(getLastName))


Nach Ihrem Beispiel müssen Sie nach zwei Feldern (Nachname, Vorname) und nicht nach einem Feld sortieren. Sie können die Alasql Bibliothek verwenden, um diese Sortierung in einer Zeile vorzunehmen:

var res = alasql('SELECT * FROM ? ORDER BY last_nom, first_nom',[objs]);

Versuchen Sie es mit jsFiddle .


function compare(propName) {
    return function(a,b) {
        if (a[propName] < b[propName])
            return -1;
        if (a[propName] > b[propName])
            return 1;
        return 0;
    };
}

objs.sort(compare("last_nom"));




sorting