Як я можу зробити сортування asc та desc за допомогою underscore.js?


166

Я зараз використовую підкреслення для сортування мого json сортування. Тепер я попросив зробити ascendingі descendingсортування за допомогою underscore.js. Я нічого не бачу щодо того ж у документації. Як я можу цього досягти?


1
Будь ласка, додайте приклад того, що ви сортуєте та як.
Джон

Що ви сортуєте? Числа? Струни? Дати? Щось ще?
mu занадто короткий,

@muistooshort Я сортую масив об'єктів. Тож метод sortBy ідеально відповідає моїм критеріям для висхідного сортування, але не навпаки.
Рахул

Якщо ви сортуєте за числом, то ваша sortByфункція може бути, return -nале це не буде працювати для рядків; звідси питання про те, які речі ви сортуєте.
mu занадто короткий

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
Останнє рішення, тобто додавання знака-відродження до повернутого числа, є ідеальним.
vinesh

Чому б ти думав, що це сорти міхура? Під капотом .sortBy()вбудований вхід Array.sort(), алгоритм якого залежить від постачальників браузера, але сортування бульбашок навряд чи буде їх вибором.
Рене Саарсоо

Це не збільшує трудомісткість? Це призводить до сортування списку двічі.
користувач1477388

@ user1477388 Я не впевнений, що ти маєш на увазі про сортування двічі?
andlrc

@andlrc Отже, коли ви телефонуєте _.sortBy(arr, function), я припускаю, що він перетинає кожен елемент і виконує певну логіку для повернення відсортованого масиву. Потім, коли ви називаєте Array.prototype.reverse()це, ймовірно, повторно перетинає кожен елемент і виконує певну логіку, щоб повернути повернений масив. Тому ви двічі лупаєте масив.
користувач1477388

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 (), щоб отримати значення unicode.

//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, функція (число) {SOME_FUNC ...});
aqm

4
charCodeAt "поверне Unicode символу у вказаному індексі в рядку", тому його можна використовувати для сортування за символами в рядку, але, як показано, він не "сортує за рядком", він сортує за символом у рядку
Ентоні

2
Це сортування лише за першим символом, і він враховує регістри.
помічник

50

У зворотному методі масиву прототип змінює масив і повертає посилання на нього, що означає , що ви можете зробити це:

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

Також документація підкреслення:

Крім того, методи прототипу Array проксі через ланцюговий об'єкт підкреслення, тому ви можете ковзати a reverseабо a pushу свій ланцюг і продовжувати змінювати масив.

а це означає, що ви також можете користуватися .reverse()ланцюгом:

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

Це за проїздом найпростіший метод зворотного / низхідного сортування, коли мова йде про найбільш простих випадках використання.
Ден Аткінсон

2
Зробити алфавітний сорт, що не відрізняється від регістру:_.sortBy(collection, item => item. propertyName.toLowerCase());
XåpplI'-I0llwlg'I -

це не працює, якщо в масиві є негативні числа.
Шруті Капур

@ShrutiKapoor Так. Чому б і ні?
Еміль Лундберг

5
З точки зору продуктивності, бажано спочатку застосувати фільтр, а потім сортувати (інші) значення.
Саран

12

Аналогічно бібліотеці підкреслення є ще одна бібліотека, яка називається "lodash", яка має один метод "orderBy", який приймає в параметрі визначення того, в якому порядку сортувати її. Ви можете користуватися нею

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

Чомусь це не зафіксовано на документах на веб-сайті.


Я думаю, ти переплутав підкреслення з лодашем . Тільки останній має згадану функцію orderBy .
Томас Марті

Так, мій поганий. Відповідь буде оновлено. Дякуємо за виправлення :)
Minkesh Jain

orderBy, супер корисно! Набагато краще, ніж використовувати реверс, оскільки він зберігає стабільну властивість сортування, яку я шукаю.
Flimm

З мене чомусь не працює оновлення: його 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.