Sortuj tablicę obiektów według wartości właściwości string

Mam tablicę obiektów JavaScript:

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

Jak mogę sortować je według wartości last_nom w JavaScript?

Wiem o sort(a,b), ale to działa tylko na ciągi i liczby. Czy muszę dodawać metodę toString() do moich obiektów?

Author: Alexander Abakumov, 2009-07-15

30 answers

Łatwo jest napisać własną funkcję porównawczą:

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

Lub inline (c/O):

objs.sort((a,b) => (a.last_nom > b.last_nom) ? 1 : ((b.last_nom > a.last_nom) ? -1 : 0)); 
 2841
Author: Wogan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-19 13:48:01

Możesz również utworzyć dynamiczną funkcję sortowania, która sortuje obiekty według ich wartości, które przekazujesz:

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

Więc możesz mieć tablicę obiektów takich jak:

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

...i będzie działać, gdy to zrobisz:

People.sort(dynamicSort("Name"));
People.sort(dynamicSort("Surname"));
People.sort(dynamicSort("-Surname"));
To już odpowiada na pytanie. Poniżej część jest napisana, ponieważ wiele osób skontaktowało się ze mną, narzekając, że to nie działa z wieloma parametrami.

Wiele Parametrów

Możesz użyć poniższej funkcji do wygenerowania sortowania funkcje z wieloma parametrami sortowania.

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

Które pozwoliłyby Ci zrobić coś takiego:

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

Dodanie Go Do Prototypu

(implementacja, która jest tuż poniżej jest inspirowana Mike R ' s odpowiedz)

Nie zalecałbym zmiany natywnego prototypu obiektu, ale tylko po to, aby podać przykład, abyś mógł zaimplementować go na własnych obiektach (w środowiskach, które go obsługują, możesz również użyć obiekt.defineProperty Jak pokazano w następnej sekcji, która przynajmniej nie ma negatywnego efektu ubocznego bycia wyliczalnym, jak opisano w ostatniej części)

Implementacja prototypu byłaby podobna do poniższego ( oto działający przykład):

//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));
    }
}();
W przeciwieństwie do poprzednich wersji, nie jest to możliwe.]}

Jeśli celujesz w IE v9. 0 i nowsze, to, jak już wspomniałem, użyj Object.defineProperty like this (working przykład):

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

Może to być akceptowalny kompromis, dopóki nie pojawi sięoperator bind .

Wszystkie te prototypowe zabawy umożliwiają to:

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

Powinieneś To Przeczytać

Jeśli użyjesz metody direct prototype access (Object.defineProperty jest w porządku), a inny kod nie sprawdza hasOwnProperty , kocięta umierają! Ok, szczerze mówiąc, żadna krzywda nie spotka żadnego kotka naprawdę, ale prawdopodobnie wszystko się zepsuje i każdy inny programista w Twoim zespole będzie nienawidził ty:

zło

Widzisz to ostatnie "SortBy"? Tak. Niefajnie. Użyj Obiektu.defineProperty gdzie można, i zostawić tablicę.tylko prototyp.
 670
Author: Ege Özcan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:37

Podkreślam.js

Użyj podkreślenia, jego małe i niesamowite...

SortBy_.sortBy (list, iterator, [context]) zwraca posortowaną kopię lista, uszeregowana w kolejności rosnącej według wyników uruchomienia każdej wartości poprzez iterator. Iterator może być również nazwą łańcuchową właściwości do sortowania według (np. długość).

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
Author: David Morrow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-10 19:34:40

W ES6 / ES2015 lub nowszym możesz zrobić tak:

objs.sort((a, b) => a.last_nom.localeCompare(b.last_nom));
 156
Author: Vlad Bezden,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-29 19:44:37

Nie rozumiem, dlaczego ludzie tak to komplikują:

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

Dla silnikow:

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

Zamień operatora, aby posortował go według odwrotnej kolejności alfabetycznej.

 146
Author: p3lim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-22 19:25:59

Jeśli masz zduplikowane nazwiska, możesz posortować je po imieniu -

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
Author: kennebec,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-29 18:35:50

Proste i szybkie rozwiązanie tego problemu przy użyciu dziedziczenia prototypów:

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

Przykład / Użycie

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: nie modyfikuje już oryginalnej tablicy.

 38
Author: Vinay Aggarwal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-15 21:45:09

Zamiast używać niestandardowej funkcji porównywania, można również utworzyć typ obiektu z niestandardową metodą toString() (która jest wywoływana przez domyślną funkcję porównywania):

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
Author: Christoph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-15 07:21:48

Jest tu wiele dobrych odpowiedzi, ale chciałbym podkreślić, że można je bardzo łatwo rozszerzyć, aby osiągnąć o wiele bardziej złożone sortowanie. Jedyne, co musisz zrobić, to użyć operatora OR do łączenia funkcji porównawczych w taki sposób:

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

Gdzie fn1, fn2, ... są funkcjami sortującymi, które zwracają [-1,0,1]. Powoduje to "sortowanie według fn1", "sortowanie według fn2", które jest prawie równe ORDER BY w SQL.

Rozwiązanie to opiera się na zachowaniu || operator, który oblicza na pierwsze ocenione wyrażenie, które można przekonwertować na true .

Najprostsza forma mA tylko jedną funkcję inlined, taką jak ta:

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

Mając dwa kroki z last_nom,first_nom kolejność sortowania wyglądałaby tak:

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

Ogólna funkcja porównawcza może wyglądać następująco:

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

Ta funkcja może być rozszerzona o obsługę pól liczbowych, case Sensity, arbitary datatypes itd.

Możesz ich używać z łańcuchowaniem ich według priorytetu sortowania:

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

Chodzi o to, że czysty JavaScript z podejściem funkcjonalnym może zabrać cię daleko bez zewnętrznych bibliotek lub skomplikowanego kodu. Jest to również bardzo skuteczne, ponieważ nie ma potrzeby parsowania napisów

 15
Author: Tero Tolonen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-05 11:36:14

Przykładowe Użycie:

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

Skrypt:

/**
 * @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
Author: fold_left,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-30 10:02:43

Wiem, że to pytanie jest za stare, ale nie widziałem żadnej implementacji podobnej do mojej.
Ta wersja jest oparta na idiomie 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);
}

Oto przykład jak z niego korzystać:

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
Author: a8m,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-06 13:26:18

Lodash.js (superset of Underscore.js )

Dobrze jest nie dodawać frameworka dla każdego prostego kawałka logiki, ale poleganie na dobrze przetestowanych frameworkach narzędziowych, przyspieszenie rozwoju i zmniejszenie ilości napisanych błędów nie jest wstydem.

Lodash tworzy bardzo czysty kod i promuje bardziej styl programowania funkcyjnego , co powoduje mniej błędów. W jednym spojrzeniu staje się jasne, co intencji, jeśli kod jest.

Problem OP może być po prostu rozwiązany jako:

const sortedObjs = _.sortBy(objs, 'last_nom');
Więcej informacji? Np. mamy następujący zagnieżdżony obiekt:
const users = [
  { 'user': {'name':'fred', 'age': 48}},
  { 'user': {'name':'barney', 'age': 36 }},
  { 'user': {'name':'wilma'}},
  { 'user': {'name':'betty', 'age': 32}}
];

Możemy teraz użyć _.właściwość Skrót user.age aby określić ścieżkę do właściwości, które mają być dopasowane. Obiekty użytkownika posortujemy według zagnieżdżonej właściwości age. Tak, pozwala na dopasowanie zagnieżdżonych właściwości!

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

Chcesz to odwrócić? Nie ma sprawy. Użyj _.reverse .

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

Chcesz połączyć oba za pomocą Łańcuchowania zamiast tego?

const sortedObjs = _.chain(users).sortBy('user.age').reverse().value();
 14
Author: Nico Van Belle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-23 22:42:27

Sortowanie (więcej) złożonych tablic obiektów

Ponieważ prawdopodobnie napotkasz bardziej złożone struktury danych, takie jak ta tablica, rozszerzyłbym rozwiązanie.

TL;DR

Są bardziej pluggable wersja oparta na @ege-Özcan's very lovely odpowiedz .

Problem

Spotkałem się z poniższym i nie mogłem go zmienić. Nie chciałem też chwilowo spłaszczyć obiektu. Nie chciałem też używać podkreślenia / lodash, głównie ze względów wydajnościowych i zabawy w samodzielne wdrożenie.

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

Gol

Celem jest sortowanie go przede wszystkim według People.Name.name, a po drugie według People.Name.surname

Przeszkody

Teraz, w rozwiązaniu podstawowym używa notacji nawiasowej do dynamicznego obliczania właściwości do sortowania. W tym przypadku musielibyśmy również dynamicznie konstruować notację wspornika, ponieważ spodziewalibyśmy się, że niektóre podobne People['Name.name'] będą działać - co nie działa.

Po prostu robić People['Name']['name'], z drugiej ręka, jest statyczna i pozwala tylko zejść w dół N-TH poziomu.

Rozwiązanie

Głównym dodatkiem będzie przejście w dół drzewa obiektów i określenie wartości ostatniego liścia, musisz określić, jak również każdego liścia pośredniego.

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

Przykład

Przykład roboczy na JSBin

 12
Author: eljefedelrodeodeljefe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:33

Mam kawałek kodu, który działa dla mnie:

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

UPDATE: nie działa zawsze, więc nie jest poprawne: (

 12
Author: Damjan Pavlica,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-07 22:51:14

Prosty sposób:

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

Zobacz, że '.toLowerCase()' jest konieczne, aby zapobiec erros w porównywaniu ciągów.

 9
Author: Caio Ladislau,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-15 13:32:57

Od 2018 roku istnieje znacznie krótsze i eleganckie rozwiązanie. Po prostu użyj. Array.prototyp.sort () .

Przykład:

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
Author: Oleg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-04 15:24:36

Połączenie dynamicznego rozwiązania Ege z pomysłem Vinay ' a daje solidne rozwiązanie:]}

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

Użycie:

// 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
Author: Mike R,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-23 16:07:34

Dodatkowe desc params dla Ege Özcan kod

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
Author: Behnam Yousefi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-16 20:22:18

Zgodnie z Twoim przykładem, musisz sortować według dwóch pól (nazwisko, imię), a nie jednego. Możesz użyć biblioteki Alasql Aby sortować w jednym wierszu:

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

Spróbuj tego przykładu w jsFiddle .

 7
Author: agershun,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-18 11:09:04

Jeszcze jedna opcja:

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

Sortuje domyślnie rosnąco.

 7
Author: Ravshan Samandarov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-26 09:10:05

Może być konieczne przekonwertowanie ich na małe litery, aby zapobiec zamieszaniu.

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
Author: Burak Keceli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-14 10:40:10
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
Author: Evgenii,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-29 13:09:48
objs.sort(function(a,b){return b.last_nom>a.last_nom})
 6
Author: Roshni Bokade,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-08 09:51:36

Nie widziałem tego konkretnego podejścia sugerowanego, więc oto krótka metoda porównania, którą lubię używać, która działa zarówno dla string i 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))

Oto Wyjaśnienie sortBy():

sortBy() przyjmuje fn, która wybiera wartość z obiektu do porównania i zwraca funkcję, którą można przekazać bezpośrednio do Array.prototype.sort(). W tym przykładzie używamy o.last_nom jako wartości do porównania, więc za każdym razem, gdy otrzymujemy dwa obiekty przez Array.prototype.sort() takie jak

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

I

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

Używamy

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

Aby je porównać.

Pamiętając, że fn = o => o.last_nom, możemy rozszerzyć funkcję compare do odpowiednika

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

Operator logiczny lub || ma bardzo przydatną tutaj funkcję zwarcia. Ze względu na sposób działania, ciało powyższej funkcji oznacza

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

Więc jeśli a < b zwracamy -1, w przeciwnym razie jeśli a > b to zwracamy +1, ale jeśli a == b, to a < b i a > b są false, więc zwraca +0.

Jako dodatkowy bonus, oto odpowiednik w ECMAScript 5.1 bez funkcji strzałek, który niestety nie jest tak zwięzły:]}

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
Author: Patrick Roberts,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-18 09:53:13

To prosty problem, Nie wiem, dlaczego ludzie mają tak złożone rozwiązanie.
Prosta funkcja sortowania (oparta na algorytmie quick-sort ):

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

Użyj przykładu:

var myArr = 
        [
            { val: 'x', idx: 3 },
            { val: 'y', idx: 2 },
            { val: 'z', idx: 5 },
        ];
myArr = sortObjectsArray(myArr, 'idx');
 5
Author: Gil Epshtain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-19 14:27:57

Using 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
Author: Sridhar Sg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-05 07:43:55

Właśnie ulepszyłem dynamiczne sortowanie Ege Özcan, aby zanurkować głęboko w obiektach. Jeśli dane wyglądają tak:

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

I jeśli chcesz to uporządkować A. a myślę, że moje ulepszenie bardzo pomaga. Dodaję nowe funkcjonalności do takich obiektów:

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

And changed _dynamicSort's return function:

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

A teraz możesz sortować według a. a. w ten sposób:

obj.sortBy('a.a');

Zobacz skrypt Commplete w JSFiddle

 4
Author: Morteza Tourani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:03:09

Podany oryginalny przykład:

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

Sortuj według wielu pól:

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

Uwagi

  • a.localeCompare(b) jest i zwraca -1,0,1 jeśli a<b,a==b,a>b odpowiednio.
  • || w ostatniej linijce podano last_nom priorytet nad first_nom.
  • odejmowanie działa na polach liczbowych: var age_order = left.age - right.age;
  • negować do odwrotnej kolejności, return -last_nom_order || -first_nom_order || -age_order;
 4
Author: Bob Stein,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-24 00:54:56

Używając lodash lub Underscore, to bułka z masłem

> const sortedList = _.orderBy(objs, [last_nom], [asc]); // asc or desc
 3
Author: karthik006,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-26 05:40:06

Sposób 1:

Możesz użyć Underscore.js. Najpierw zaimportuj podkreślenie.

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

Sposób 2: Użyj funkcji Porównaj.

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
Author: Harunur Rashid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-17 23:04:45