Vraag Sorteer de reeks objecten op tekenreekswaarde in JavaScript


Ik heb een array van JavaScript-objecten:

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

Hoe kan ik ze sorteren op de waarde van last_nom in JavaScript?

ik weet over sort(a,b), maar dat lijkt alleen te werken op strings en cijfers. Moet ik een toString-methode aan mijn objecten toevoegen?


1815
2017-07-15 03:17


oorsprong


antwoorden:


Het is eenvoudig genoeg om uw eigen vergelijkingsfunctie te schrijven:

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

Of 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



U kunt ook een dynamische sorteerfunctie maken die objecten sorteert op basis van de waarde die u doorgeeft:

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

U kunt dus een reeks objecten als deze hebben:

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

... en het zal werken als je dat doet:

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

Eigenlijk is dit al een antwoord op de vraag. Onderstaand deel is geschreven omdat veel mensen contact met me hebben opgenomen en daarover klagen het werkt niet met meerdere parameters.

Meerdere parameters

U kunt de onderstaande functie gebruiken om sorteerfuncties te genereren met meerdere sorteerparameters.

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

Dat zou u in staat stellen om zoiets als dit te doen:

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

Het toevoegen aan het prototype

(Implementatie die net onder is, is geïnspireerd op Mike R's antwoord)

Ik zou niet aanraden een prototype van een native object te wijzigen, maar alleen om een ​​voorbeeld te geven, zodat u het op uw eigen objecten kunt implementeren (Voor de omgevingen die dit ondersteunen, kunt u ook gebruiken Object.defineProperty zoals getoond in de volgende sectie, die tenminste niet het negatieve neveneffect heeft van opsombaar te zijn, zoals beschreven in het laatste deel)

De implementatie van prototypen zou ongeveer het volgende zijn (Hier is een werkend voorbeeld):

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

De "OK" manier om het aan het prototype toe te voegen

Als u IE v9.0 en hoger target, dan gebruikt u, zoals ik eerder al zei Object.defineProperty soortgelijk (werkend voorbeeld):

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

Dit kan een acceptabel compromis zijn tot de binden operator arriveert.

Al die prototypeplezier maakt dit mogelijk:

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

Je zou dit moeten lezen

Als u de directe prototype-toegangsmethode gebruikt (Object.defineProperty is prima) en andere code niet controleert hasOwnProperty, kittens sterven! Oké, om eerlijk te zijn, geen kwaad kan een kitten krijgen, maar waarschijnlijk zullen dingen breken en elke andere ontwikkelaar in je team zal je haten:

evil

Zie je dat laatste "SortBy"? Ja. Niet cool. Gebruik Object.defineProperty waar u kunt en laat het Array.prototype anders alleen.


649
2018-01-21 15:03



underscore.js

gebruik onderstrepingsteken, het is klein en geweldig ...

sortBy_.sortBy (lijst, iterator, [context]) Retourneert een gesorteerde kopie van   lijst, gerangschikt in oplopende volgorde door de resultaten van het uitvoeren van elke waarde   via iterator. Iterator kan ook de tekenreeksnaam van het onroerend goed zijn   sorteren op (bijv. lengte).

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



Begrijp niet waarom mensen het zo ingewikkeld maken:

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

Voor strengere motoren:

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

Ruil de operator om deze op alfabetische volgorde te laten sorteren.


140
2018-01-24 19:35



In ES6 / ES2015 of later kunt u het volgende doen:

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

136
2018-01-29 19:44



Als u dubbele achternaam heeft, kunt u deze sorteren op voornaam:

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



Eenvoudige en snelle oplossing voor dit probleem door overerving van 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;
  });
}

Voorbeeld / gebruik

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

Bijwerken: Wijzigt niet langer de oorspronkelijke array.


38
2017-07-10 11:54