Как я могу сделать asc и desc сортировку, используя underscore.js?


166

В настоящее время я использую underscorejs для сортировки JSON сортировки. Теперь я попросил сделать ascendingи descendingсортировку с использованием underscore.js. Я не вижу ничего похожего в документации. Как мне этого добиться?


1
Пожалуйста, добавьте пример того, что вы сортируете и как.
— Джон

Что вы сортируете? Числа? Строки? Сроки? Что-то другое?
— Му слишком коротко

@muistooshort Я сортирую массив объектов. Таким образом, метод sortBy идеально подходит моим критериям для сортировки по возрастанию, но не наоборот.
— Рахул

Если вы сортируете по числу, то ваша sortByфункция может быть, return -nно это не сработает для строк; отсюда вопрос о том, какие вещи вы сортируете.
— мю слишком коротка

2
С Lodash вы можете использовать сокращение _.sortBy([1,4,3,2]).reverse()или как, _.chain([1,4,3,2]).sortBy().reverse().value()если вы не хотите использовать reverse()прототип Array.
— GFoley83

Ответы:


363

Вы можете использовать .sortBy, он всегда вернет список по возрастанию :

_.sortBy([2, 3, 1], function(num) {
    return num;
}); // [1, 2, 3]

Но вы можете использовать метод .reverse, чтобы получить его по убыванию :

var array = _.sortBy([2, 3, 1], function(num) {
    return num;
});

console.log(array); // [1, 2, 3]
console.log(array.reverse()); // [3, 2, 1]

Или при работе с числами добавьте отрицательный знак к возврату, чтобы убрать список:

_.sortBy([-3, -2, 2, 3, 1, 0, -1], function(num) {
    return -num;
}); // [3, 2, 1, 0, -1, -2, -3]

Под капотом .sortByиспользуются встроенные .sort([handler]):

// Default is ascending:
[2, 3, 1].sort(); // [1, 2, 3]

// But can be descending if you provide a sort handler:
[2, 3, 1].sort(function(a, b) {
    // a = current item in array
    // b = next item in array
    return b - a;
});

9
Последнее решение, т.е. добавление отрицательного знака к возвращаемому num, идеально.
— Винеш

Почему вы думаете, что это пузырьковая сортировка? Под капотом .sortBy()называются встроенные функции Array.sort(), алгоритм которых зависит от производителей браузеров, но пузырьковая сортировка вряд ли будет их выбором.
— Рене Саарсоо

Разве это не увеличивает сложность времени? Это приводит к тому, что список сортируется дважды.
— user1477388

@ user1477388 Я не уверен, что ты имеешь в виду, отсортированный дважды?
— andlrc

@andlrc Итак, когда вы вызываете _.sortBy(arr, function), я предполагаю, что он зацикливается на каждом элементе и выполняет некоторую логику, чтобы вернуть отсортированный массив. Затем, когда вы вызываете Array.prototype.reverse()его, вероятно, снова зацикливается на каждом элементе и выполняет некоторую логику для возврата обращенного массива. Таким образом, вы зацикливаете массив дважды.
— user1477388

57

По убыванию, используя подчеркивание, можно сделать, умножив возвращаемое значение на -1.

//Ascending Order:
_.sortBy([2, 3, 1], function(num){
    return num;
}); // [1, 2, 3]


//Descending Order:
_.sortBy([2, 3, 1], function(num){
    return num * -1;
}); // [3, 2, 1]

Если вы сортируете по строкам, а не по номерам, вы можете использовать метод charCodeAt (), чтобы получить значение Юникода.

//Descending Order Strings:
_.sortBy(['a', 'b', 'c'], function(s){ 
    return s.charCodeAt() * -1;
});

3
Я пытаюсь отсортировать по алфавиту - умножение на -1 не является допустимой операцией. :)
— rythos42

Это стоит использовать, но не указано в вопросе. Однако умножение строки на -1 является допустимой операцией. Он возвращает NaN, который является действительным результатом.
— JeremyB

1
не забудьте назначить массив обратно тоже! SOME_ARR = _.sortBy (SOME_ARR, function (num) {SOME_FUNC ...});
— АКМ

4
charCodeAt будет «возвращать Unicode символа по указанному индексу в строке», поэтому его можно использовать для сортировки по символам в строке, но, как показано, он не «сортирует по строке», а сортирует по символу в строке
— Энтони

2
Сортирует только по первому символу и учитывает регистр.
— Эйдан

50

В обратном методе массива прототип изменяет массив и возвращает ссылку на него, что означает , что вы можете сделать это:

var sortedAsc = _.sortBy(collection, 'propertyName');
var sortedDesc = _.sortBy(collection, 'propertyName').reverse();

Также подчеркивающая документация гласит:

Кроме того, методы прототипа Array проксируются через связанный объект Underscore, так что вы можете вставить reverseили pushв свою цепочку и продолжить модифицировать массив.

это означает, что вы также можете использовать .reverse()во время цепочки:

var sortedDescAndFiltered = _.chain(collection)
    .sortBy('propertyName')
    .reverse()
    .filter(_.property('isGood'))
    .value();

Это самый простой способ для обратной / нисходящей сортировки, когда речь идет о самых простых случаях использования.
— Дэн Аткинсон

2
Для алфавитной сортировки _.sortBy(collection, item => item. propertyName.toLowerCase());
— без учета

это не работает, если в массиве есть отрицательные числа.
— Шрути Капур

@ShrutiKapoor Да, это так. Почему бы и нет?
— Эмиль Лундберг

5
Что касается производительности, было бы предпочтительно сначала применить фильтр, а затем отсортировать (оставшиеся) значения.
— Саран

12

По аналогии с библиотекой Underscore есть еще одна библиотека с именем lodash, в которой есть один метод orderBy, который принимает параметр для определения порядка сортировки. Вы можете использовать его как

_.orderBy('collection', 'propertyName', 'desc')

По какой-то причине, это не задокументировано на сайте документации.


Я думаю, что вы перепутали подчеркивание с lodash . Только последний имеет упомянутую функцию orderBy .
— Томас Марти

Да, мой плохой. Обновлю ответ. Спасибо за исправление :)
— Минкеш Джайн

orderByсупер полезно! Гораздо лучше, чем использование reverse, поскольку он сохраняет свойство стабильной сортировки, которое я ищу.
— Flimm

Не работает для меня почему-то upadte: его lodash (
— aleXela

0

Подчеркни Миксин

Расширяя ответ @ emil_lundberg, вы также можете написать «mixin», если вы используете Underscore для создания пользовательской функции для сортировки, если это своего рода сортировка, которую вы могли бы повторить в приложении где-нибудь.

Например, может быть, у вас есть контроллер или просмотр результатов сортировки с порядком сортировки «ASC» или «DESC», и вы хотите переключаться между ними, вы можете сделать что-то вроде этого:

Mixin.js

_.mixin({
    sortByOrder: function(stooges, prop, order) {
      if (String(order) === "desc") {
          return _.sortBy(stooges, prop).reverse();
      } else if (String(order) === "asc") {
          return _.sortBy(stooges, prop);
      } else {
          return stooges;
      }
    }
})

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

var sort_order = "asc";
var stooges = [
  {name: 'moe', age: 40}, 
  {name: 'larry', age: 50}, 
  {name: 'curly', age: 60},
  {name: 'July', age: 35},
  {name: 'mel', age: 38}
 ];

_.mixin({
    sortByOrder: function(stooges, prop, order) {
    if (String(order) === "desc") {
        return _.sortBy(stooges, prop).reverse();
    } else if (String(order) === "asc") {
        return _.sortBy(stooges, prop);
    } else {
        return stooges;
    }
  }
})


// find elements
var banner = $("#banner-message");
var sort_name_btn = $("button.sort-name");
var sort_age_btn = $("button.sort-age");

function showSortedResults(results, sort_order, prop) {
    banner.empty();
    banner.append("<p>Sorting: " + prop + ', ' + sort_order + "</p><hr>")
  _.each(results, function(r) {
    banner.append('<li>' + r.name + ' is '+ r.age + ' years old.</li>');
  }) 
}

// handle click and add class
sort_name_btn.on("click", function() {
  sort_order = (sort_order === "asc") ? "desc" : "asc"; 
    var sortedResults = _.sortByOrder(stooges, 'name', sort_order);
  showSortedResults(sortedResults, sort_order, 'name');
})

sort_age_btn.on('click', function() {
    sort_order = (sort_order === "asc") ? "desc" : "asc"; 
    var sortedResults = _.sortByOrder(stooges, 'age', sort_order);
  showSortedResults(sortedResults, sort_order, 'age');
})

Вот JSFiddle, демонстрирующий это: JSFiddle для SortBy Mixin

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.