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ę posortować je według wartości last_nom w JavaScript?

Wiem o sort(a,b), ale wydaje się, że tylko działa na ciągach i liczbach. Czy muszę dodać metodę toString() do moich obiektów?

3363
Tyrone Slothrop 15 lipiec 2009, 07:17

28 odpowiedzi

Najlepsza odpowiedź

Jest wystarczająco łatwy, aby napisać własną funkcję porównania:

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 Marco Demaio):

objs.sort((a,b) => (a.last_nom > b.last_nom) ? 1 : ((b.last_nom > a.last_nom) ? -1 : 0)); 
4357
João Pimentel Ferreira 20 styczeń 2021, 22:18

Możesz także utworzyć funkcję sortowania dynamicznego, która sortuje obiekty według ich wartości, którą mijasz:

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

Więc możesz mieć taką tablicę obiektów:

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

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

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

Właściwie to już odpowiada na pytanie. Poniżej części jest napisana, ponieważ wielu ludzi skontaktowała się ze mną, narzekając, że Nie działa z wieloma parametrami.

Wiele parametrów.

Możesz użyć poniższej funkcji, aby wygenerować funkcje sortowania 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;
    }
}

Co pozwoli ci zrobić coś takiego:

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

Tablica podklasy

Na szczęście wśród nas, którzy mogą korzystać z ES6, co pozwala rozszerzyć rodzime obiekty:

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

To umożliwiłoby to:

MyArray.from(People).sortBy("Name", "-Surname");
893
Ege Özcan 13 grudzień 2020, 09:49

W ES6 / ES2015 lub później możesz zrobić w ten sposób:

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

Przed ES6 / ES2015

objs.sort(function(a, b) {
    return a.last_nom.localeCompare(b.last_nom)
});
529
Victor Ifeanyi Ejiogu 8 listopad 2019, 17:11

Nie rozumiem, dlaczego ludzie robią to tak skomplikowane:

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

Dla surowszych silników:

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 odwrócone zamówienie alfabetyczne.

179
p3lim 22 kwiecień 2014, 19:25

Właśnie ulepszam EGE Özcan Sortowanie dynamiczne, aby nurkować głęboko wewnętrzne obiekty. 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 }
}];

A jeśli chcesz go sortować ponad a.a , myślę, że moje ulepszenie pomaga bardzo dobrze. Dodam nowe funkcjonalność 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;
    }
});

I zmienił _Dynamicsort Funkcja zwrotu

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ć przez A.a. w ten sposób:

obj.sortBy('a.a');

Zobacz skrypt commplete w jsfiddle

5
Community 23 maj 2017, 12:03

Jeśli masz duplikaty nazwisk, możesz sortować te imię

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;
});
70
BadFeelingAboutThis 29 kwiecień 2014, 18:35

Proste i szybkie rozwiązanie tego problemu za pomocą dziedziczenia prototypu:

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

Aktualizacja: Nie modyfikuje już oryginalnej tablicy.

54
Web_Designer 15 maj 2015, 21:45

Od 2018 r. Istnieje znacznie krótsze i eleganckie rozwiązanie. Po prostu użyj. array.prototype.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;
});
47
0leg 4 czerwiec 2018, 15:24

Stara odpowiedź, która nie jest poprawna:

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

AKTUALIZACJA

Z komentarza Beauchampa:

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

Bardziej czytelny format:

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

Bez zagnieżdżonych ternarodowych:

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

Objaśnienie: Number() rzuci true do 1 i false do 0.

44
Damjan Pavlica 24 grudzień 2019, 21:38

Lodash.js (SuperSet of Underscore.js)

Dobrze nie dodawać ramy dla każdego prostego kawałka logiki, ale opierając się na dobrze przetestowanych ramach narzędziowych może przyspieszyć opracowanie i zmniejszyć ilość błędów.

Lodash produkuje bardzo czysty kod i promuje więcej funkcjonalne programowanie styl. W jednym spojrzeniu staje się jasne, jakie jest zamiar kodu.

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

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

Więcej informacji? Na przykład. Mamy podążał za zagnieżdżonym obiektem:

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

Teraz możemy używać _.Property Shorthand {x0}}, aby określić ścieżkę do właściwości, która powinna być dopasowana. Sortujemy obiekty użytkownika przez nieruchomość zagnieżdżenia. Tak, pozwala na zagnieżdżone pasujące do nieruchomości!

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

Chcesz odwrócić? Nie ma problemu. Użyj _.Reverse.

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

Chcesz połączyć zarówno za pomocą łańcuch?

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

Lub kiedy wolisz przepływ nad łańcuchem

const { flow, reverse, sortBy } = require('lodash/fp');
const sortedObjs = flow([sortBy('user.age'), reverse])(users); 
39
Nico Van Belle 4 marzec 2020, 09:41

Nie widziałem, że te szczególne podejście sugerowało, więc oto metodę porównania tchanu, które lubię używać, które 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) => {
  const fa = fn(a)
  const fb = fn(b)
  return -(fa < fb) || +(fa > fb)
}
const getLastName = o => o.last_nom
const sortByLastName = sortBy(getLastName)

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

Oto wyjaśnienie sortBy():

sortBy() Akceptuje fn, który wybiera wartość z obiektu, aby użyć jako porównania i zwraca funkcję, która może być przekazywana bezpośrednio do Array.prototype.sort(). W tym przykładzie, używamy o.last_nom jako wartość dla porównania, więc za każdym razem, gdy otrzymamy dwa obiekty za pomocą Array.prototype.sort() takie jak

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

I

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

Używamy

(a, b) => {
  const fa = fn(a)
  const fb = fn(b)
  return -(fa < fb) || +(fa > fb)
}

Porównać je.

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

(a, b) => {
  const fa = a.last_nom
  const fb = b.last_nom
  return -(fa < fb) || +(fa > fb)
}

Operator logiczny lub || ma funkcjonalność zwarcia, która jest bardzo przydatna tutaj. Ze względu na to, jak działa, ciało funkcji powyżej oznacza

if (fa < fb) return -1
return +(fa > fb)

Więc jeśli fa < fb Wrócimy -1, w przeciwnym razie, jeśli fa > fb wówczas wracamy +1, ale jeśli fa == fb, a następnie fa > fb i fa > fb } Czy false, więc zwraca +0.

Jako dodatkowy bonus, oto odpowiednik w ECMASCRIPT 5 bez funkcji strzałek, który jest niestety więcej pełniejszy:

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) {
    var fa = fn(a)
    var fb = fn(b)
    return -(fa < fb) || +(fa > fb)
  }
}

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

objs.sort(sortByLastName)
console.log(objs.map(getLastName))
33
Patrick Roberts 9 lipiec 2020, 15:38

Zamiast korzystać z niestandardowej funkcji porównania, można również utworzyć typ obiektu z metodą niestandardową {X0}} (która jest wywołana przez domyślną funkcję porównania):

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();
32
Christoph 15 lipiec 2009, 07:21

Możesz użyć

Najłatwiej: Lodash

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

Ta metoda jest jak _.sortby, z wyjątkiem tego, że pozwala na określenie zleceń sortowania itererów do sortowania. Jeśli zamówienia są nieokreślone, wszystkie wartości są sortowane w kolejności rosnącej. W przeciwnym razie określ kolejność "DESC" dla malejącego lub "ASC" dla rosnących kolejności sortowania odpowiednich wartości.

Argumenty

Kolekcja (tablica | obiekt): Kolekcja do itera. [ITERESES = [_. Identity]] (tablica [] | Funkcja [] | obiekt [] | String []): Iteria do sortowania. [Zamówienia] (ciąg []): Sortowanie poleceń iteracji.

Zwroty

(Array): Zwraca nową sortowaną tablicę.


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']);
30
Harvey 23 sierpień 2018, 14:39

Jest tu wiele dobrych odpowiedzi, ale chciałbym zwrócić uwagę, że można je rozszerzyć, aby uzyskać wiele bardziej złożonych sortowania. Jedyną rzeczą, którą musisz zrobić, to użyć funkcji porównania lub funkcji operatora do łańcucha:

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

Gdzie fn2, fn2, ... są funkcjami sortowania, które zwracają [-1,0,1]. Powoduje to "sortowanie przez FN1", "Sortowanie przez FN2", co jest prawie równe zamówić w SQL.

To rozwiązanie opiera się na operatorze ||, który ocenia się do Pierwsze ocenione wyrażenie, które można konwertować na true.

Najprostsza forma ma tylko jedną w taką funkcję:

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

Mając dwa kroki z last_nom, first_nom porządek sortowania wyglądałby 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ównania może być taka:

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

Funkcja ta może zostać rozszerzona na wsparcie pól numerycznych, czułość przypadku, dowolnych typów danych itp.

Możesz je wykorzystać z łańcuchem 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 długą drogę bez bibliotek zewnętrznych lub złożonego kodu. Jest również bardzo skuteczny, ponieważ nie trzeba zrobić parsowanie ciągów

26
Tero Tolonen 5 maj 2016, 11:36

Przykładowe zastosowanie:

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

Scenariusz:

/**
 * @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;
  };
};
24
Jamie Mason 21 marzec 2019, 17:18

Sortowanie (więcej) Kompleksowe tablice obiektów

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

TL; DR

Są bardziej wtyczkową w oparciu o @ Ege-Özcan jest bardzo piękny Odpowiedź.

Problem

Spotkałem poniżej i nie mogłem go zmienić. Nie chciałem tymczasowo spłaszczyć obiektu. Nie chciałem też używać podkreślenia / Lodash, głównie ze względów wydajności i zabawy, aby sam go wdrożyć.

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

Cel

Celem jest posortowanie go głównie przez People.Name.name i wtórnie przez People.Name.surname

Przeszkody

Teraz w rozwiązaniu bazowym wykorzystuje notację wspornika, aby obliczyć właściwości do ich dynamicznie. Tutaj jednak będziemy musieli skonstruować notacji wspornika również dynamicznie, ponieważ spodziewałbyś się, że niektórzy People['Name.name'] będzie działać - co nie.

Po prostu robienie People['Name']['name'], z drugiej strony jest statyczne i pozwala zejść do poziomu n -th.

Rozwiązanie

Głównym dodatkiem będzie przejść do drzewa obiektowego i określi wartość ostatniego liścia, musisz określić, a także dowolny liść pośredni.

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 On Jsbin

15
Community 23 maj 2017, 12:18

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ące.

14
Ravshan Samandarov 26 czerwiec 2016, 09:10

Prosty sposób:

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

Zobacz, że '.toLowerCase()' jest konieczne, aby zapobiec błędom w porównaniu ciągów.

11
Caio Ladislau 15 styczeń 2016, 13:32

Prosta funkcja, która sortująca tablicę obiektu przez nieruchomość

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
}

Stosowanie:

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
11
Francois Girard 28 maj 2018, 19:54

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;
    }
}
10
Behnam Shomali 16 wrzesień 2012, 20:22

Łącząc dynamiczne rozwiązanie EGE z pomysłem Vinay, otrzymasz ładny solidny 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));
}

Stosowanie:

// 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");
10
Mike R 23 kwiecień 2013, 16:07
objs.sort(function(a,b){return b.last_nom>a.last_nom})
9
Ben Carp 11 grudzień 2020, 12:42

Abording twój przykład, musisz sortować przez dwa pola (nazwisko, imię), a następnie jeden. Możesz użyć alasql biblioteka, aby tego rodzaju w jednej linii:

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

Spróbuj tego przykładu w Jsfiddle.

8
agershun 18 grudzień 2014, 11:09

Za pomocą ramdy,

NPM Zainstaluj 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)
8
Sridhar Sg 5 lipiec 2017, 07:43

Biorąc pod uwagę 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

  • {{X0}. , a==b, a>b odpowiednio.
  • || W ostatniej linii daje last_nom priorytet nad first_nom.
  • Odejmowanie działa na polach numerycznych: var age_order = left.age - right.age;
  • Negować do odwrotnej kolejności, return -last_nom_order || -first_nom_order || -age_order;
8
Bob Stein 24 luty 2018, 00:54

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

})
7
Burak Keceli 14 sierpień 2013, 10:40
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"));
7
Evgenii 29 październik 2015, 13:09

Jest to prosty problem, nie wiem, dlaczego ludzie mają takie złożone rozwiązanie.
Prosta funkcja sortowania (na podstawie Quick-sort algorytm):

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');
7
Gil Epshtain 19 listopad 2015, 14:27