Jak mogę posortować rosnąco i malejąco za pomocą underscore.js?


166

Obecnie używam znaków podkreślenia do sortowania plików JSON. Teraz poprosiłem o wykonanie ascendingi descendingsortowanie przy użyciu podkreślenia.js. Nie widzę w dokumentacji nic o tym samym. Jak mogę to osiągnąć?


1
Dodaj przykład tego, co sortujesz i jak.
— Jon

Co sortujesz? Liczby? Smyczki? Daktyle? Coś innego?
— mu jest za krótkie

@muistooshort Sortuję tablicę obiektów. Zatem metoda sortBy doskonale pasuje do moich kryteriów sortowania rosnącego, ale nie na odwrót.
— Rahul

Jeśli sortujesz według liczby, twoja sortByfunkcja może być, return -nale to nie zadziała w przypadku łańcuchów; stąd pytanie, jakie rzeczy sortujesz.
— mu jest za krótkie

2
W Lodash możesz używać shorthand like _.sortBy([1,4,3,2]).reverse()lub _.chain([1,4,3,2]).sortBy().reverse().value()jeśli nie chcesz używać reverse()prototypu Array.
— GFoley83,

Odpowiedzi:


363

Możesz użyć .sortBy, zawsze zwróci listę rosnącą :

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

Ale możesz użyć metody .reverse , aby uzyskać malejąco :

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

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

Lub w przypadku liczb dodaj znak minus do powrotu, aby zejść z listy:

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

Pod maską .sortByzastosowano wbudowane .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
Ostatnie rozwiązanie tj. Dodanie znaku ujemnego do zwracanej liczby jest idealne.
— Vinesh

Dlaczego myślisz, że to sortowanie bąbelkowe? .sortBy()Wbudowane wywołania pod maską Array.sort(), których algorytm zależy od dostawców przeglądarek, ale sortowanie bąbelkowe raczej nie będzie ich wyborem.
— Rene Saarsoo,

Czy to nie zwiększa złożoności czasowej? Powoduje to dwukrotne posortowanie listy.
— user1477388

@ user1477388 Nie jestem pewien, co masz na myśli, mówiąc o sortowaniu dwukrotnie?
— andlrc

@andlrc Tak więc, kiedy dzwonisz _.sortBy(arr, function), zakładam, że zapętla się nad każdym elementem i wykonuje jakąś logikę, aby zwrócić posortowaną tablicę. Następnie, gdy wywołasz Array.prototype.reverse()to, prawdopodobnie ponownie zapętli się nad każdym elementem i wykonuje jakąś logikę, aby zwrócić odwróconą tablicę. Dlatego dwukrotnie zapętlasz tablicę.
— user1477388

57

Porządek malejący za pomocą podkreślenia można wykonać, mnożąc zwracaną wartość przez -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]

Jeśli sortujesz według ciągów, a nie liczb, możesz użyć metody charCodeAt (), aby uzyskać wartość Unicode.

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

3
Próbuję posortować alfabetycznie - mnożenie przez -1 nie jest prawidłową operacją. :)
— rythos42

Warto go użyć, ale nie został określony w pytaniu. Jednak pomnożenie ciągu przez -1 jest prawidłową operacją. Zwraca NaN, który jest prawidłowym wynikiem.
— jEremyB

1
pamiętaj o ponownym przypisaniu tablicy! SOME_ARR = _.sortBy (SOME_ARR, function (num) {SOME_FUNC ...});
— aqm

4
charCodeAt „zwróci kod Unicode znaku o określonym indeksie w ciągu”, dzięki czemu można go użyć do sortowania według znaków w ciągu, ale jak pokazano, nie sortuje według ciągu, sortuje według znaku w ciągu
— Anthony

2
Sortuje tylko według pierwszego znaku i rozróżnia wielkość liter.
— Aidan

50

Tego prototypu Array metoda odwróconej modyfikuje tablicy i zwraca referencję do niego, co oznacza, że można to zrobić:

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

Ponadto dokumentacja z podkreśleniem czyta:

Ponadto metody prototypu Array są przesyłane przez serwer proxy za pośrednictwem połączonego obiektu Underscore, dzięki czemu można wsunąć a reverselub a pushdo łańcucha i kontynuować modyfikowanie tablicy.

co oznacza, że ​​możesz również użyć .reverse()podczas łączenia:

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

Jest to najprostsza metoda sortowania odwrotnego / malejącego, jeśli chodzi o najprostsze przypadki użycia.
— Dan Atkinson

2
Aby wykonać sortowanie alfabetyczne bez rozróżniania wielkości liter:_.sortBy(collection, item => item. propertyName.toLowerCase());
— XåpplI'-I0llwlg'I -

to nie działa, jeśli w tablicy są liczby ujemne.
— Shruti Kapoor,

@ShrutiKapoor Tak, to prawda. Dlaczego by tego nie zrobił?
— Emil Lundberg

5
Ze względu na wydajność najlepiej byłoby najpierw zastosować filtr, a następnie posortować (pozostałe) wartości.
— Saran,

12

Podobnie jak w przypadku biblioteki Underscore, istnieje inna biblioteka o nazwie „lodash”, która ma jedną metodę „orderBy”, która pobiera parametr w celu określenia kolejności sortowania. Możesz go używać jak

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

Z jakiegoś powodu nie jest to udokumentowane w dokumentacji witryny.


Myślę, że pomyliłeś podkreślenie z lodash . Tylko ta ostatnia ma wspomnianą funkcję orderBy .
— Thomas Marti

Tak, moja wina. Zaktualizuje odpowiedź. Dzięki za poprawienie :)
— Minkesh Jain

orderBy, super przydatne! Znacznie lepsze niż używanie odwrócenia, ponieważ zachowuje stabilną właściwość sortowania, której szukam.
— Flimm

Z jakiegoś powodu nie działa dla mnie upadte: jego lodash (
— aleXela

0

Mixins podkreślenia

Rozszerzając odpowiedź @ emil_lundberg, możesz również napisać „mixin”, jeśli używasz podkreślenia, aby utworzyć niestandardową funkcję do sortowania, jeśli jest to rodzaj sortowania, który możesz powtórzyć w jakiejś aplikacji.

Na przykład, być może masz kontroler lub widok sortowania wyników z porządkiem sortowania „ASC” lub „DESC” i chcesz przełączać się między tym sortowaniem, możesz zrobić coś takiego:

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

Przykład użycia

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

Oto JSFiddle demonstrujący to: JSFiddle dla SortBy Mixin

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.