Як я можу зробити сортування 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.