Sorteer array van objecten op tekenreekseigenschapswaarde

Ik heb een array met 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_nomin JavaScript?

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


Antwoord 1, autoriteit 100%

Het is gemakkelijk 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((a,b) => (a.last_nom > b.last_nom) ? 1 : ((b.last_nom > a.last_nom) ? -1 : 0))

Antwoord 2, autoriteit 20%

U kunt ook een dynamische sorteerfunctie maken die objecten sorteert op hun waarde die u doorgeeft:

function dynamicSort(property) {
    var sortOrder = 1;
    if(property[0] === "-") {
        sortOrder = -1;
        property = property.substr(1);
    }
    return function (a,b) {
        /* next line works with strings and numbers, 
         * and you may want to customize it to your needs
         */
        var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
        return result * sortOrder;
    }
}

Je kunt dus een array van objecten hebben zoals deze:

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 beantwoordt dit de vraag al. Het onderstaande gedeelte is geschreven omdat veel mensen contact met mij hebben opgenomen en klaagden dat het niet werkt 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;
    }
}

Waarmee je zoiets als dit zou kunnen doen:

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

Array subklassen

Voor de gelukkigen onder ons die ES6 kunnen gebruiken, waarmee de oorspronkelijke objecten kunnen worden uitgebreid:

class MyArray extends Array {
    sortBy(...args) {
        return this.sort(dynamicSortMultiple(...args));
    }
}

Dat zou dit mogelijk maken:

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

Antwoord 3, autoriteit 14%

In ES6/ES2015 of later kun je dit op deze manier doen:

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

Vóór ES6/ES2015

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

Antwoord 4, autoriteit 4%

underscore.js

gebruik onderstrepingsteken, het is klein en geweldig…

sortBy_.sortBy(list, iterator, [context]) Geeft een gesorteerde kopie van
lijst, gerangschikt in oplopende volgorde op basis van de resultaten van het uitvoeren van elke waarde
via iterator. Iterator kan ook de tekenreeksnaam van de eigenschap zijn
om te 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' );

Antwoord 5, autoriteit 2%

Als je dubbele achternamen hebt, kun je die 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;
});

Antwoord 6

Eenvoudige en snelle oplossing voor dit probleem met behulp van prototype-overerving:

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

Update:wijzigt niet langer de originele array.


Antwoord 7

Vanaf 2018 is er een veel kortere en elegantere oplossing. Gebruik gewoon. Array.prototype.sort().

Voorbeeld:

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

Antwoord 8

Oud antwoord dat niet correct is:

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

UPDATE

Uit de opmerking van Beauchamp:

arr.sort((a, b) => a.name < b.name ? -1 : (a.name > b.name ? 1 : 0))

Beter leesbaar formaat:

arr.sort((a, b) => {
  if (a.name < b.name) return -1
  return a.name > b.name ? 1 : 0
})

Zonder geneste ternaries:

arr.sort((a, b) => a.name < b.name ? - 1 : Number(a.name > b.name))

Uitleg: Number()cast truenaar 1en falsenaar 0.


Antwoord 9

Lodash.js(superset van Underscore.js)

Het is goed om niet voor elk simpel stukje logica een framework toe te voegen, maar vertrouwen op goed geteste hulpprogramma-frameworks kan de ontwikkeling versnellen en het aantal bugs verminderen.

Lodash produceert zeer zuivere code en promoot een meer functionele programmeerstijl. In één oogopslag wordt duidelijk wat de bedoeling van de code is.

OP’s probleem kan eenvoudig worden opgelost als:

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

Meer info? bijv. we hebben het volgende geneste object:

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

We kunnen nu de _.propertyverkorte user.ageom het pad op te geven naar de eigenschap die moet worden gekoppeld. We sorteren de gebruikersobjecten op de eigenschap geneste leeftijd. Ja, het maakt het mogelijk om geneste eigenschappen te matchen!

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

Wilt u het terugdraaien? Geen probleem. Gebruik _.reverse.

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

Wilt u beide combineren met keten?

const { chain } = require('lodash');
const sortedObjs = chain(users).sortBy('user.age').reverse().value();

Of wanneer geeft u de voorkeur aan flowboven keten

const { flow, reverse, sortBy } = require('lodash/fp');
const sortedObjs = flow([sortBy('user.age'), reverse])(users); 

Antwoord 10

Ik heb deze specifieke benadering nog niet voorgesteld, dus hier is een beknopte vergelijkingsmethode die ik graag gebruik en die werkt voor zowel stringals numbertypen:

const objs = [ 
  { first_nom: 'Lazslo', last_nom: 'Jamf'     },
  { first_nom: 'Pig',    last_nom: 'Bodine'   },
  { first_nom: 'Pirate', last_nom: 'Prentice' }
];
const sortBy = fn => {
  const cmp = (a, b) => -(a < b) || +(a > b);
  return (a, b) => cmp(fn(a), fn(b));
};
const getLastName = o => o.last_nom;
const sortByLastName = sortBy(getLastName);
objs.sort(sortByLastName);
console.log(objs.map(getLastName));

Antwoord 11

In plaats van een aangepaste vergelijkingsfunctie te gebruiken, kunt u ook een objecttype maken met de aangepaste toString()-methode (die wordt aangeroepen door de standaardvergelijkingsfunctie):

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

Antwoord 12

U kunt gebruiken
Eenvoudigste manier: Lodash

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

Deze methode lijkt op _.sortBybehalve dat het de mogelijkheid biedt om de sorteervolgorde van de iteraten te specificeren om op te sorteren. Als orders niet gespecificeerd zijn, worden alle waarden in oplopende volgorde gesorteerd. Geef anders een volgorde op van “desc” voor aflopende of “asc” voor oplopende sorteervolgorde van corresponderende waarden.

Argumenten

verzameling (Array|Object): de verzameling die moet worden herhaald.
[iteratees=[_.identity]] (Array[]|Function[]|Object[]|string[]): De iteraten waarop moet worden gesorteerd.
[orders] (string[]): De sorteervolgorde van iteraten.

Retourneren

(Array): Geeft de nieuwe gesorteerde array terug.


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

Antwoord 13

Er zijn hier veel goede antwoorden, maar ik wil erop wijzen dat ze heel eenvoudig kunnen worden uitgebreid om een veel complexere sortering te bereiken. Het enige dat u hoeft te doen is de OR-operator te gebruiken om vergelijkingsfuncties als volgt te ketenen:

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

Waar fn1, fn2, … de sorteerfuncties zijn die [-1,0,1] teruggeven. Dit resulteert in “sorteren op fn1”, “sorteren op fn2”, wat ongeveer gelijk is aan ORDER BY in SQL.

Deze oplossing is gebaseerd op het gedrag van de operator ||die evalueert naar de eerste geëvalueerde expressie die kan worden geconverteerd naar true.

De eenvoudigste vormheeft maar één inline-functie zoals deze:

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

Als je twee stappen hebt met last_nom, ziet de sorteervolgorde van first_nomer als volgt uit:

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

Een algemene vergelijkingsfunctiezou er ongeveer zo uit kunnen zien:

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

Deze functie kan worden uitgebreid om numerieke velden, hoofdlettergevoeligheid, willekeurige gegevenstypen enz. te ondersteunen.

Je kunt ze gebruiken door ze te koppelen op sorteerprioriteit:

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

Het punt hier is dat puur JavaScript met een functionele benadering je een heel eind kan brengen zonder externe bibliotheken of complexe code. Het is ook erg effectief, omdat er geen string-parsing hoeft te worden uitgevoerd


Antwoord 14

Voorbeeld van gebruik:

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

Script:

/**
 * @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;
  };
};

Antwoord 15

Probeer dit,

UPTO ES5
//Ascending Sort
items.sort(function (a, b) {
   return a.value - b.value;
});
//Descending Sort
items.sort(function (a, b) {
   return b.value - a.value;
});
IN ES6 & above:
// Ascending sort
items.sort((a, b) => a.value - b.value);
// Descending Sort
 items.sort((a, b) => b.value - a.value);

Antwoord 16

Ik weet dat deze vraag te oud is, maar ik heb geen implementatie gezien die lijkt op die van mij.
Deze versie is gebaseerd op het Schwartziaanse transformatie-idioom.

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 is een voorbeeld hoe het te gebruiken:

let games = [
  { name: 'Mashraki',          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'));

Antwoord 17

(meer) complexe arrays van objecten sorteren

Omdat je waarschijnlijk complexere datastructuren zoals deze array tegenkomt, zou ik de oplossing uitbreiden.

TL;DR

Zijn meer pluggable versie gebaseerd op @ege-Özcan‘ s erg mooi antwoord.

Probleem

Ik kwam het onderstaande tegen en kon het niet wijzigen. Ik wilde het object ook niet tijdelijk plat maken. Ik wilde ook geen underscore / lodash gebruiken, voornamelijk om prestatieredenen en het plezier om het zelf te implementeren.

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

Doel

Het doel is om het primair te sorteren op People.Name.nameen secundair op People.Name.surname

Obstakels

In de basisoplossing wordt nu haakjesnotatie gebruikt om de eigenschappen te berekenen waarop dynamisch moet worden gesorteerd. Maar hier zouden we de haakjesnotatie ook dynamisch moeten construeren, omdat je zou verwachten dat sommige zoals People['Name.name']zouden werken – wat niet het geval is.

Gewoon People['Name']['name']doen, is daarentegen statisch en stelt je alleen in staat om naar het n-de niveau te gaan .

Oplossing

De belangrijkste toevoeging hier is om door de objectboom te lopen en de waarde te bepalen van het laatste blad dat u moet specificeren, evenals elk tussenblad.

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

Voorbeeld

Werkvoorbeeld op JSBin


Antwoord 18

Nog een optie:

var someArray = [...];
function generateSortFn(prop, reverse) {
    return function (a, b) {
        if (a[prop] < b[prop]) return reverse ? 1 : -1;
        if (a[prop] > b[prop]) return reverse ? -1 : 1;
        return 0;
    };
}
someArray.sort(generateSortFn('name', true));

sorteert standaard oplopend.


Antwoord 19

Een eenvoudige manier:

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

Zie dat '.toLowerCase()'nodig is om fouten te voorkomen
bij het vergelijken van strings.


Antwoord 20

Hoofdlettergevoelig

arr.sort((a, b) => a.name > b.name ? 1 : -1);

Hoofdlettergevoelig

arr.sort((a, b) => a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1);

Opmerking

Als er geen verandering in de volgorde is (in het geval van dezelfde strings), dan zal de voorwaarde >mislukken en zal -1worden geretourneerd. Maar als strings hetzelfde zijn, zal het retourneren van 1 of -1 resulteren in een correcte uitvoer

De andere optie zou kunnen zijn om de operator >=te gebruiken in plaats van >


Antwoord 21

Een eenvoudige functie die een array van objecten sorteert op een eigenschap

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
}

Gebruik:

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

Antwoord 22

Waarschuwing!
Het gebruik van deze oplossing wordt niet aanbevolenomdat dit niet resulteert in een gesorteerde array. Het wordt hier achtergelaten voor toekomstig gebruik, omdat het idee niet zeldzaam is.

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

Antwoord 23

extra desc-parameters voor Ege Özcancode

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

Antwoord 24

Als je de dynamische oplossing van Ege combineert met het idee van Vinay, krijg je een mooie robuuste oplossing:

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

Gebruik:

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

Antwoord 25

Dit is mijn mening hierover:

De parameter orderis optioneel en staat standaard op “ASC” voor oplopende volgorde.

Werkt op geaccentueerde tekens en is niet hoofdlettergevoelig.

OPMERKING:het sorteert en retourneert de ORIGINELEarray.

function sanitizeToSort(str) {
  return str
    .normalize('NFD')                   // REMOVE ACCENTED AND DIACRITICS
    .replace(/[\u0300-\u036f]/g,'')     // REMOVE ACCENTED AND DIACRITICS
    .toLowerCase()                      // SORT WILL BE CASE INSENSITIVE
  ;
}
function sortByProperty(arr, property, order="ASC") {
  arr.forEach((item) => item.tempProp = sanitizeToSort(item[property]));
  arr.sort((a,b) => order === "ASC" ?
      a.tempProp > b.tempProp ?  1 : a.tempProp < b.tempProp ? -1 : 0
    : a.tempProp > b.tempProp ? -1 : a.tempProp < b.tempProp ?  1 : 0
  );
  arr.forEach((item) => delete item.tempProp);
  return arr;
}

SNIPPET

function sanitizeToSort(str) {
  return str
    .normalize('NFD')                   // REMOVE ACCENTED CHARS
    .replace(/[\u0300-\u036f]/g,'')     // REMOVE DIACRITICS
    .toLowerCase()
  ;
}
function sortByProperty(arr, property, order="ASC") {
  arr.forEach((item) => item.tempProp = sanitizeToSort(item[property]));
  arr.sort((a,b) => order === "ASC" ?
      a.tempProp > b.tempProp ?  1 : a.tempProp < b.tempProp ? -1 : 0
    : a.tempProp > b.tempProp ? -1 : a.tempProp < b.tempProp ?  1 : 0
  );
  arr.forEach((item) => delete item.tempProp);
  return arr;
}
const rockStars = [
  { name: "Axl",
    lastname: "Rose" },
  { name: "Elthon",
    lastname: "John" },
  { name: "Paul",
    lastname: "McCartney" },
  { name: "Lou",
    lastname: "Reed" },
  { name: "freddie",             // WORKS ON LOWER/UPPER CASE
    lastname: "mercury" },
  { name: "Ámy",                 // WORKS ON ACCENTED CHARS TOO
    lastname: "winehouse"}
];
sortByProperty(rockStars,"name");
console.log("Ordered by name A-Z:");
rockStars.forEach((item) => console.log(item.name + " " + item.lastname));
sortByProperty(rockStars,"lastname","DESC");
console.log("\nOrdered by lastname Z-A:");
rockStars.forEach((item) => console.log(item.lastname + ", " + item.name));

Antwoord 26

Waarom schrijf je geen korte code?

objs.sort((a, b) => a.last_nom > b.last_nom && 1 || -1)

Antwoord 27

Volgens uw voorbeeld moet u sorteren op twee velden (achternaam, voornaam), in plaats van op één. U kunt de bibliotheek Alasqlgebruiken om dit in één regel te sorteren:

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

Probeer dit voorbeeld op jsFiddle.


Antwoord 28

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

Antwoord 29

Ramda gebruiken,

npm installeer 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)

Antwoord 30

Gezien het originele voorbeeld:

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

Sorteren op meerdere velden:

objs.sort(function(left, right) {
    var last_nom_order = left.last_nom.localeCompare(right.last_nom);
    var first_nom_order = left.first_nom.localeCompare(right.first_nom);
    return last_nom_order || first_nom_order;
});

Opmerkingen

  • a.localeCompare(b)wordt algemeen ondersteunden retourneert – 1,0,1 if respectievelijk a<b,a==b,a>b.
  • ||in de laatste regel geeft last_nomprioriteit boven first_nom.
  • Aftrekken werkt op numerieke velden: var age_order = left.age - right.age;
  • Ongedaan maken om volgorde om te keren, return -last_nom_order || -first_nom_order || -age_order;

Other episodes