Сортировать массив объектов по значению свойства строки - PullRequest
2336 голосов
/ 15 июля 2009

У меня есть массив объектов JavaScript:

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

Как мне отсортировать их по значению last_nom в JavaScript?

Я знаю о sort(a,b), но это работает только со строками и числами. Нужно ли добавлять toString() метод к моим объектам?

Ответы [ 41 ]

3380 голосов
/ 15 июля 2009

Достаточно просто написать собственную функцию сравнения:

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

или встроенный (с Марко Демайо):

objs.sort((a,b) => (a.last_nom > b.last_nom) ? 1 : ((b.last_nom > a.last_nom) ? -1 : 0)); 
760 голосов
/ 21 января 2011

Вы также можете создать функцию динамической сортировки, которая сортирует объекты по значению, которое вы передаете:

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

Таким образом, вы можете иметь массив таких объектов:

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

... и это сработает, когда вы сделаете:

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

На самом деле это уже отвечает на вопрос. Ниже написано, что со мной связались многие, жалуясь, что не работает с несколькими параметрами .

Несколько параметров

Вы можете использовать приведенную ниже функцию для генерации функций сортировки с несколькими параметрами сортировки.

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

Что позволит вам сделать что-то вроде этого:

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

Массив подклассов

Для тех счастливчиков, которые могут использовать ES6, который позволяет расширять нативные объекты:

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

Это позволило бы это:

MyArray.from(People).sortBy("Name", "-Surname");
270 голосов
/ 29 января 2016

В ES6 / ES2015 или новее вы можете сделать это так:

objs.sort((a, b) => a.last_nom.localeCompare(b.last_nom));
175 голосов
/ 11 мая 2012

underscore.js

используйте подчеркивание, оно маленькое и удивительное ...

sortBy_.sortBy (список, итератор, [контекст]) Возвращает отсортированную копию список, ранжированный в порядке возрастания по результатам выполнения каждого значения через итератор. Итератор также может быть строковым именем свойства сортировать по (например, длине).

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' );
164 голосов
/ 24 января 2014

Не понимаю, почему люди так усложняют:

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

Для более строгих двигателей:

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

Поменяйте местами оператор, чтобы отсортировать его в обратном алфавитном порядке.

61 голосов
/ 15 июля 2009

Если у вас есть повторяющиеся фамилии, вы можете отсортировать их по имени-

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;
});
42 голосов
/ 10 июля 2012

Простое и быстрое решение этой проблемы с использованием наследования прототипа:

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

Пример / Использование

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

Обновление: Больше не изменяет исходный массив.

29 голосов
/ 04 июня 2018

По состоянию на 2018 год существует гораздо более короткое и элегантное решение. Просто используйте. Array.prototype.sort () .

Пример:

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;
});
28 голосов
/ 15 июля 2009

Вместо использования пользовательской функции сравнения можно также создать тип объекта с помощью пользовательского метода toString() (который вызывается функцией сравнения по умолчанию):

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();
23 голосов
/ 23 августа 2018

Вы можете использовать

Самый простой способ: Лодаш

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

Этот метод похож на _.sortBy, за исключением того, что он позволяет указывать порядок сортировки итерируемых для сортировки. Если заказы не указаны, все значения сортируются в порядке возрастания. В противном случае укажите порядок «desc» для убывания или «asc» для возрастания и сортировки соответствующих значений.

Аргументы

collection (Array | Object): коллекция для повторения. [iteratees = [_. identity]] (Array [] | Function [] | Object [] | string []): Итерации для сортировки. [orders] (string []): порядок сортировки итераций.

Returns

(Массив): возвращает новый отсортированный массив.


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']);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...