Trier le tableau d'objets par la valeur de la propriété string

j'ai un tableau D'objets JavaScript:

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

Comment puis-je les Trier par la valeur de last_nom en JavaScript?

je sais à propos de sort(a,b) , mais qui semble seulement à travailler sur des chaînes de caractères et des nombres. Dois-je ajouter une méthode toString() à mes objets?

1922
demandé sur Alexander Abakumov 2009-07-15 07:17:47
la source

30 ответов

Il est assez facile d'écrire votre propre fonction de comparaison:

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

Or inline (c/o Marco Demaio):

objs.sort((a,b) => (a.last_nom > b.last_nom) ? 1 : ((b.last_nom > a.last_nom) ? -1 : 0)); 
2841
répondu Wogan 2018-09-19 16:48:01
la source

vous pouvez également créer une fonction de tri dynamique qui trie les objets par leur valeur que vous passez:

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

donc vous pouvez avoir un tableau d'objets comme ceci:

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

...et il va travailler quand vous le faites:

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

en fait cela répond déjà à la question. Ci-dessous une partie est écrite parce que beaucoup de gens m'ont contacté, se plaignant que il ne fonctionne pas avec des paramètres multiples .

Paramètres Multiples

vous pouvez utiliser la fonction ci-dessous pour générer des fonctions de tri avec plusieurs paramètres de tri.

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

Qui vous permettrait de faire quelque chose comme ceci:

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

L'Ajoutant Au Prototype

(mise en œuvre qui est juste en dessous est inspiré de Mike R 's réponse )

Je ne recommande pas de changer un prototype d'objet natif, mais juste pour donner un exemple afin que vous puissiez l'implémenter sur vos propres objets (pour les environnements qui le supportent, vous pouvez également utiliser objet.defineProperty , comme indiqué dans la section suivante, qui au moins n'a pas les effets secondaires négatifs de énumérable, comme décrit dans la dernière partie)

quelque chose comme ce qui suit ( voici un exemple de travail ):

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

la façon " OK "de L'ajouter au Prototype

si vous visez IE v9.0 et ensuite, comme je l'ai mentionné précédemment, utiliser objet.defineProperty comme ceci ( exemple ):

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

ceci peut être un compromis acceptable jusqu'à ce que l'opérateur de liaison arrive.

tous ces plaisir prototype permet cela:

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

Vous Devriez Lire Ceci

si vous utilisez la méthode d'accès direct prototype (objet.defineProperty est très bien) et autre code ne coche pas hasOwnProperty , les chatons meurent! OK, pour être honnête, aucun mal ne vient à n'importe quel chaton vraiment, mais probablement les choses vont casser et tous les autres développeurs dans votre équipe vont vous détester:

evil

vous voyez ce dernier "SortBy"? Ouais. Pas cool. Utiliser L'Objet.définissez la propriété où vous pouvez, et quittez le tableau.prototype seul sinon.

670
répondu Ege Özcan 2017-05-23 13:31:37
la source

trait de soulignement.js

utilisez underscore, son petit et impressionnant...

sortBy_.sortBy(liste, itérateur, [contexte]) Renvoie une triés copie de liste, classée par ordre croissant par les résultats de l'exécution de chaque valeur par itérateur. Itérateur peut aussi être le nom de la chaîne de la propriété à Trier par (p. ex. longueur.)

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' );
160
répondu David Morrow 2016-03-10 22:34:40
la source

en ES6 / ES2015 ou plus tard vous pouvez faire de cette façon:

objs.sort((a, b) => a.last_nom.localeCompare(b.last_nom));
156
répondu Vlad Bezden 2016-01-29 22:44:37
la source

Ne pas comprendre pourquoi les gens font-il si compliqué:

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

pour les moteurs plus stricts:

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

changez l'opérateur pour qu'il soit trié par ordre alphabétique inversé.

146
répondu p3lim 2014-04-22 23:25:59
la source

si vous avez des noms de famille en double, vous pouvez les Trier par prénom -

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;
});
52
répondu kennebec 2014-04-29 22:35:50
la source

solution Simple et rapide à ce problème en utilisant l'héritage de prototype:

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

Exemple / Usage

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

mise à jour: ne modifie plus le tableau original.

38
répondu Vinay Aggarwal 2015-05-16 00:45:09
la source

au lieu d'utiliser une fonction de comparaison personnalisée, vous pouvez aussi créer un type d'objet avec la méthode personnalisée toString() (qui est invoquée par la fonction de comparaison par défaut):

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();
24
répondu Christoph 2009-07-15 11:21:48
la source

il y a beaucoup de bonnes réponses ici, mais je voudrais souligner qu'elles peuvent être étendues très simplement pour obtenir un tri beaucoup plus complexe. La seule chose que vous devez faire est d'utiliser L'opérateur OR pour enchaîner les fonctions de comparaison comme ceci:

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

fn1 , fn2 , ... sont les fonctions qui retournent [-1,0,1]. Il en résulte un" tri par fn1", un" tri par fn2 " qui est à peu près égal à L'ordre Par in SQL.

Cette solution est basée sur le comportement de l'opérateur || qui évalue à la la première expression évaluée qui peut être convertie en vraie .

la forme la plus simple a une seule fonction inlined comme ceci:

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

ayant deux étapes avec last_nom , first_nom ordre de tri ressemblerait à ceci:

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

A la fonction de comparaison Générique pourrait être quelque chose comme ceci:

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

cette fonction pourrait être étendue pour prendre en charge les champs numériques, les cas sensibilisés, les types de données arbitaires, etc.

vous pouvez les utiliser en les enchaînant par ordre de priorité:

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

le point ici est que JavaScript pur avec approche fonctionnelle peut vous prendre un long chemin sans bibliothèques externes ou code complexe. Il est également très efficace, puisqu'aucun parsing de chaîne ne doit être fait

15
répondu Tero Tolonen 2016-05-05 14:36:14
la source

Exemple D'Usage:

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}     
 */
function 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.
  var 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.
  var moveLarger = reverse ? -1 : 1;

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

}
14
répondu fold_left 2014-04-30 14:02:43
la source

je sais que cette question est trop ancienne, mais je n'ai pas vu d'implémentation similaire à la mienne.

Cette version est basée sur L'idiome Schwartzian transform .

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

voici un exemple d'utilisation:

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'));
14
répondu a8m 2016-11-06 16:26:18
la source

Lodash.js (superset de Underscore.js )

il est bon de ne pas ajouter un cadre pour chaque simple morceau de logique, mais en s'appuyant sur des cadres d'utilité bien testés, accélérer le développement et réduire la quantité de bogues écrits n'est pas une honte.

Lodash produit du code très propre et favorise un plus programmation fonctionnelle style, ce qui entraîne moins de bugs. Dans un aperçu il devient clair que l'intention si le code est.

OP problème peut être simplement résolu que:

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

plus d'information? Par exemple: nous avons l'objet suivant imbriqué:

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

Nous pouvons maintenant utiliser le _.propriété raccourci user.age pour spécifier le chemin de la propriété qui doit être apparié. Nous allons trier les objets utilisateurs par la propriété age imbriquée. Oui, il permet la propriété imbriquée correspondant!

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

voulez-vous que ce soit inversé? Pas de problème. Utilisez _.inversez .

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

vous voulez combiner les deux en utilisant chaînage à la place?

const sortedObjs = _.chain(users).sortBy('user.age').reverse().value();
14
répondu Nico Van Belle 2018-01-24 01:42:27
la source

Tri (plus) de matrices complexes d'objets

puisque vous rencontrez probablement des structures de données plus complexes comme ce tableau, je voudrais étendre la solution.

TL; DR

Sont plus enfichable version basée sur @gee-Özcan très belle réponse .

Problème

J'ai rencontré le dessous et je n'ai pas pu le changer. Je ne voulais pas d'aplatir l'objet temporairement. Je ne voulais pas non plus utiliser underscore / lodash, principalement pour des raisons de performance et le plaisir de l'implémenter moi-même.

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

Objectif

le but est de le trier principalement par People.Name.name et secondairement par People.Name.surname

Obstacles

maintenant, dans la solution de base utilise la notation de support pour calculer les propriétés à trier dynamiquement. Ici, cependant, nous aurions à construire la notation de bracket dynamiquement aussi, puisque vous vous attendez à ce que certains comme People['Name.name'] fonctionnerait - ce qui ne fonctionne pas.

simplement faire People['Name']['name'] , d'autre part, est statique et vous permet seulement de descendre le niveau n - th.

Solution

l'addition principale ici sera de marcher le long de l'arbre d'objet et de déterminer la valeur de la dernière feuille, vous devez spécifier, ainsi que toute feuille intermédiaire.

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

exemple

exemple pratique on JSBin "1519160920

12
répondu eljefedelrodeodeljefe 2017-05-23 15:18:33
la source

j'ai un morceau de code qui fonctionne pour moi:

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

mise à jour: ne fonctionne pas toujours, il n'est donc pas correct: (

12
répondu Damjan Pavlica 2017-12-08 01:51:14
la source

Une manière simple:

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

voir que '.toLowerCase()' est nécessaire pour prévenir les erreurs en comparant les chaînes.

9
répondu Caio Ladislau 2016-01-15 16:32:57
la source

à partir de 2018 il y a une solution beaucoup plus courte et élégante. Juste à l'utiliser. tableau.prototype.sort () .

exemple:

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;
});
9
répondu Oleg 2018-06-04 18:24:36
la source

en combinant la solution dynamique D'Ege avec L'idée de Vinay, vous obtenez une solution robuste:

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

Utilisation:

// 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");
8
répondu Mike R 2013-04-23 20:07:34
la source

paramètres supplémentaires desc pour 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;
    }
}
7
répondu Behnam Yousefi 2012-09-17 00:22:18
la source

selon votre exemple, vous devez Trier par deux champs (Nom de famille, prénom), plutôt que par un. Vous pouvez utiliser Alasql bibliothèque pour faire ce tri dans une ligne:

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

Essayez cet exemple à jsFiddle .

7
répondu agershun 2014-12-18 14:09:04
la source

une option de plus:

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

trie Ascendant Par défaut.

7
répondu Ravshan Samandarov 2016-06-26 12:10:05
la source

vous pouvez avoir besoin de les convertir en minuscules afin d'éviter toute confusion.

objs.sort(function (a,b) {

var nameA=a.last_nom.toLowerCase(), nameB=b.last_nom.toLowerCase()

if (nameA < nameB)
  return -1;
if (nameA > nameB)
  return 1;
return 0;  //no sorting

})
6
répondu Burak Keceli 2013-08-14 14:40:10
la source
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"));
6
répondu Evgenii 2015-10-29 16:09:48
la source
objs.sort(function(a,b){return b.last_nom>a.last_nom})
6
répondu Roshni Bokade 2016-03-08 12:51:36
la source

Je n'ai pas vu cette approche particulière suggéré, donc voici une méthode de comparaison terse que j'aime utiliser qui fonctionne à la fois pour string et 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))

voici une explication de sortBy() :

sortBy() accepte un fn qui sélectionne quelle valeur d'un objet à utiliser comme comparaison, et renvoie une fonction qui peut être passée directement à Array.prototype.sort() . Dans ce exemple, nous utilisons o.last_nom comme valeur de comparaison, donc chaque fois que nous recevons deux objets à travers Array.prototype.sort() comme

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

et

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

nous utilisons des

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

pour les comparer.

en se rappelant que fn = o => o.last_nom , nous pouvons étendre la fonction comparer à l'équivalent

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

l'opérateur logique ou || a un fonctionnalité de court-circuitage qui est très utile ici. En raison de la façon dont il fonctionne, le corps de la fonction ci-dessus signifie

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

donc si a < b nous retournons -1 , sinon si a > b alors nous retournons +1 , mais si a == b , alors a < b et a > b sont faux, donc il retourne +0 .

comme bonus supplémentaire, voici L'équivalent en ECMAScript 5.1 sans fonctions de flèche, qui est malheureusement pas tout à fait comme laconique:

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))
6
répondu Patrick Roberts 2018-07-18 12:53:13
la source

C'est un problème simple, Je ne sais pas pourquoi les gens ont une solution aussi complexe.

Une fonction de tri simple (basée sur Quick-sort algorithme):

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

utiliser l'exemple:

var myArr = 
        [
            { val: 'x', idx: 3 },
            { val: 'y', idx: 2 },
            { val: 'z', idx: 5 },
        ];
myArr = sortObjectsArray(myArr, 'idx');
5
répondu Gil Epshtain 2015-11-19 17:27:57
la source

Utilisant Ramda,

npm install 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)
5
répondu Sridhar Sg 2017-07-05 10:43:55
la source

j'ai Juste amélioré Ege Özcan dynamique de tri à la plongée profonde à l'intérieur des objets. Si les données ressemblent à ceci:

obj = [
    {
        a: { a: 1, b: 2, c: 3 },
        b: { a: 4, b: 5, c: 6 }
    },
    { 
        a: { a: 3, b: 2, c: 1 },
        b: { a: 6, b: 5, c: 4 }
}];

et si vous voulez trier sur A. une propriété je pense que mon amélioration aide très bien. J'ajoute de nouvelles fonctionnalités à des objets comme celui-ci:

Object.defineProperty(Object.prototype, 'deepVal', {
    enumerable: false,
    writable: true,
    value: function (propertyChain) {
        var levels = propertyChain.split('.');
        parent = this;
        for (var i = 0; i < levels.length; i++) {
            if (!parent[levels[i]])
                return undefined;
            parent = parent[levels[i]];
        }
        return parent;
    }
});

et modifié _dynamicSort 's retour fonction:

return function (a,b) {
        var result = ((a.deepVal(property) > b.deepVal(property)) - (a.deepVal(property) < b.deepVal(property)));
        return result * sortOrder;
    }

et maintenant vous pouvez trier par A. A. par ici:

obj.sortBy('a.a');

Voir Commplete script dans JSFiddle

4
répondu Morteza Tourani 2017-05-23 15:03:09
la source

dans l'exemple original:

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

Trier par champs multiples:

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

Notes

  • a.localeCompare(b) est universellement pris en charge et renvoie -1,0,1 si a<b , a==b , a>b respectivement.
  • || dans la dernière ligne donne last_nom la priorité sur les first_nom .
  • soustraction travaux sur les champs numériques: var age_order = left.age - right.age;
  • Inverser pour inverser l'ordre, return -last_nom_order || -first_nom_order || -age_order;
4
répondu Bob Stein 2018-02-24 03:54:56
la source

utilisant lodash ou Underscore, c'est un morceau de gâteau

> const sortedList = _.orderBy(objs, [last_nom], [asc]); // asc or desc
3
répondu karthik006 2018-03-26 08:40:06
la source

Voie 1 :

vous pouvez utiliser Underscore.js . Importation de souligner en premier.

 import * as _ from 'underscore';
 let SortedObjs = _.sortBy(objs, 'last_nom');

voie 2: utiliser la fonction comparer.

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

objs.sort(compare);
3
répondu Harunur Rashid 2018-06-18 02:04:45
la source

Autres questions sur javascript sorting arrays