Я пытаюсь отсортировать массив с объектами на основе нескольких атрибутов. То есть, если первый атрибут у двух объектов одинаковый, следует использовать второй атрибут для сравнения двух объектов. Например, рассмотрим следующий массив:
var patients = [
[{name: 'John', roomNumber: 1, bedNumber: 1}],
[{name: 'Lisa', roomNumber: 1, bedNumber: 2}],
[{name: 'Chris', roomNumber: 2, bedNumber: 1}],
[{name: 'Omar', roomNumber: 3, bedNumber: 1}]
];
Сортировка их по roomNumber
атрибуту, я бы использовал следующий код:
var sortedArray = _.sortBy(patients, function(patient) {
return patient[0].roomNumber;
});
Это нормально работает, но как мне поступить, чтобы «Джон» и «Лиза» были отсортированы правильно?
источник
[0]
Индексатор требуется потому , что в исходном примере,patients
представляет собой массив из массивов. Вот почему «более простое решение» в сообщении блога, упомянутое в другом комментарии, здесь не сработает.Вот хитрый прием, который я иногда использую в таких случаях: объедините свойства таким образом, чтобы результат можно было сортировать:
Однако, как я уже сказал, это довольно взломано. Чтобы сделать это правильно, вы, вероятно, захотите использовать основной
sort
метод JavaScript :Конечно, это отсортирует ваш массив на месте. Если вам нужна отсортированная копия (вроде
_.sortBy
бы вам), сначала клонируйте массив:От скуки я просто написал общее решение (для сортировки по произвольному количеству клавиш) и для этого: посмотрите .
источник
return [patient[0].roomNumber, patient[0].name];
безjoin
?compare
значение ручки , которые не являются примитивными значениями -undefined
,null
или простых объекты?Я знаю, что опаздываю на вечеринку, но я хотел добавить это для тех, кто нуждается в более быстром и чистом решении, которое те уже предложили. Вы можете связать вызовы sortBy в порядке от наименее важного свойства к наиболее важному. В приведенном ниже коде я создаю новый массив пациентов, отсортированных по имени в пределах RoomNumber из исходного массива с именем пациенты .
источник
Кстати, ваш инициализатор для пациентов немного странный, не так ли? почему бы вам не инициализировать эту переменную как это - как настоящий массив объектов - вы можете сделать это с помощью _.flatten (), а не как массив массивов одного объекта, возможно, это проблема опечатки):
Я отсортировал список по-другому и положил Кико в кровать Лизы; просто для удовольствия и посмотрите, какие изменения будут внесены ...
осмотрите отсортированный, и вы увидите это
поэтому мой ответ: используйте массив в своей функции обратного вызова это очень похоже на ответ Дэна Тао , я просто забываю соединение (возможно, потому, что я удалил массив массивов уникального элемента :))
Используя вашу структуру данных, тогда он было бы :
и тестовая нагрузка была бы интересной ...
источник
Ни один из этих ответов не является идеальным в качестве универсального метода для использования нескольких полей при сортировке. Все вышеперечисленные подходы неэффективны, так как они либо требуют сортировки массива несколько раз (что в достаточно большом списке может сильно замедлить работу), либо генерируют огромное количество мусорных объектов, которые виртуальной машине нужно будет очистить (и, в конечном итоге, замедлить программа выключена).
Вот решение, которое является быстрым, эффективным, легко допускает обратную сортировку и может использоваться с
underscore
илиlodash
или напрямую сArray.sort
Самая важная часть - это
compositeComparator
метод, который принимает массив функций компаратора и возвращает новую функцию составного компаратора.Вам также понадобится функция компаратора для сравнения полей, которые вы хотите отсортировать.
naturalSort
Функция будет создать компаратор с учетом конкретной области. Написание компаратора для обратной сортировки тоже тривиально.(Весь код до сих пор можно использовать повторно и, например, можно сохранить в служебном модуле)
Далее вам нужно создать составной компаратор. В нашем примере это будет выглядеть так:
Это будет отсортировано по номеру комнаты, а затем по имени. Добавление дополнительных критериев сортировки тривиально и не влияет на производительность сортировки.
Возвращает следующее
Причина, по которой я предпочитаю этот метод, заключается в том, что он позволяет выполнять быструю сортировку по произвольному количеству полей, не генерирует много мусора и не выполняет конкатенацию строк внутри сортировки и может легко использоваться, чтобы некоторые столбцы были отсортированы в обратном порядке, в то время как столбцы порядка используют естественный Сортировать.
источник
Простой пример из http://janetriley.net/2014/12/sort-on-multiple-keys-with-underscores-sortby.html (любезно предоставлен @MikeDevenney)
Код
С вашими данными
источник
Возможно, underscore.js или просто движки Javascript сейчас отличаются от того, когда были написаны эти ответы, но я смог решить эту проблему, просто вернув массив ключей сортировки.
Посмотрите на эту скрипку в действии: https://jsfiddle.net/mikeular/xenu3u91/
источник
Просто верните массив свойств вы хотите отсортировать:
Синтаксис ES6
Синтаксис ES5
Это не имеет побочных эффектов преобразования числа в строку.
источник
Вы можете объединить свойства, которые хотите отсортировать, в итераторе:
или что-то подобное.
ПРИМЕЧАНИЕ. Поскольку вы преобразуете числовой атрибут roomNumber в строку, вам нужно будет что-то сделать, если у вас номера комнат> 10. В противном случае 11 будет перед 2. Для решения проблемы вы можете заполнить начальными нулями, то есть 01 вместо 1.
источник
Думаю, вам лучше использовать
_.orderBy
вместоsortBy
:источник
_.orderBy
работает, но это метод библиотеки lodash, а не подчеркивания: lodash.com/docs/4.17.4#orderBy lodash в основном заменяет подчеркивание, поэтому он может быть подходящим для OP.Если вы используете Angular, вы можете использовать его числовой фильтр в html-файле, а не добавлять обработчики JS или CSS. Например:
В этом примере, если val = 1234567, оно будет отображаться как
Пример и дальнейшее руководство: https://docs.angularjs.org/api/ng/filter/number.
источник