Come posso fare un ordinamento asc e desc usando underscore.js?


166

Attualmente sto usando underscorejs per ordinare il mio ordinamento JSON. Ora ho chiesto di fare un ascendinge descendingordinamento utilizzando underscore.js. Non vedo nulla riguardo allo stesso nella documentazione. Come posso raggiungere questo obiettivo?


1
Aggiungi un esempio di ciò che stai ordinando e come.
Jon,

Cosa stai ordinando? Numeri? Stringhe? Date? Qualcos'altro?
mu è troppo corto il

@muistooshort Sto ordinando una serie di oggetti. Quindi il metodo sortBy si adatta perfettamente ai miei criteri per l'ordinamento crescente, ma non viceversa.
Rahul

Se stai ordinando per un numero, la tua sortByfunzione può essere return -nma non funzionerà per le stringhe; da qui la domanda su quali tipi di cose stai ordinando.
mu è troppo corto il

2
Con Lodash puoi usare la stenografia come _.sortBy([1,4,3,2]).reverse()o _.chain([1,4,3,2]).sortBy().reverse().value()se non vuoi usare il reverse()prototipo di Array.
GFoley83,

Risposte:


363

È possibile utilizzare .sortBy, restituirà sempre un elenco crescente :

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

Ma puoi usare il metodo .reverse per farlo scendere :

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

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

O quando hai a che fare con i numeri aggiungi un segno negativo al ritorno per discendere l'elenco:

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

Sotto il cofano .sortByutilizza il incorporato .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
L'ultima soluzione, vale a dire l'aggiunta di segni negativi al numero restituito, è perfetta.
vigna

Perché pensi che sia il bubble sort? Under the hood .sortBy()chiama built-in Array.sort(), il cui algoritmo dipende dai fornitori del browser, ma è improbabile che la scelta delle bolle sia la loro scelta.
Rene Saarsoo,

Ciò non aumenta la complessità temporale? Fa sì che l'elenco venga ordinato due volte.
user1477388

@ user1477388 Non sono sicuro di cosa intendi per due volte ordinato?
Andlrc,

@andlrc Quindi, quando chiami _.sortBy(arr, function), suppongo che giri su ogni elemento ed esegua una logica per restituire l'array ordinato. Quindi, quando lo chiami Array.prototype.reverse(), probabilmente ricomincia da capo su ogni elemento ed esegue una logica per restituire l'array invertito. Pertanto, si esegue il looping dell'array due volte.
user1477388

57

L'ordine decrescente usando il trattino basso può essere fatto moltiplicando il valore restituito per -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]

Se stai ordinando per stringhe non numeri, puoi usare il metodo charCodeAt () per ottenere il valore unicode.

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

3
Sto cercando di ordinare in ordine alfabetico - moltiplicare per -1 non è un'operazione valida. :)
rythos42,

Vale la pena usare il caso ma non specificato nella domanda. Tuttavia, moltiplicare una stringa per -1 è un'operazione valida. Restituisce NaN, che è un risultato valido.
jEremyB

1
ricordati di assegnare anche l'array! SOME_ARR = _.sortBy (SOME_ARR, funzione (num) {SOME_FUNC ...});
aqm

4
charCodeAt "restituirà l'Unicode del carattere nell'indice specificato in una stringa" in modo che possa essere utilizzato per ordinare in base a caratteri in una stringa, ma come mostrato non "ordina per stringa", ordina in base a un carattere nella stringa
Anthony,

2
Ordina solo per il primo carattere ed è sensibile al maiuscolo / minuscolo.
aidan

50

Il metodo inverso del prototipo di array modifica l'array e restituisce un riferimento ad esso, il che significa che è possibile farlo:

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

Inoltre, la documentazione di sottolineatura recita:

Inoltre, i metodi del prototipo dell'array vengono sottoposti a proxy tramite l'oggetto concatenato concatenato, quindi è possibile inserire a reverseo a pushnella catena e continuare a modificare l'array.

il che significa che puoi anche usare .reverse()mentre concateni:

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

Questo è per tariffa il metodo più semplice per l'ordinamento inverso / decrescente quando si tratta della maggior parte dei casi d'uso.
Dan Atkinson,

2
Per eseguire un ordinamento alfabetico senza distinzione tra maiuscole e minuscole:_.sortBy(collection, item => item. propertyName.toLowerCase());
XåpplI'-I0llwlg'I -

questo non funziona se ci sono numeri negativi nella matrice.
Shruti Kapoor,

@ShrutiKapoor Sì, lo fa. Perché non dovrebbe?
Emil Lundberg,

5
Per quanto riguarda le prestazioni, sarebbe preferibile applicare prima il filtro e quindi ordinare (i restanti) valori.
Saran,

12

Simile alla libreria Underscore c'è un'altra libreria chiamata 'lodash' che ha un metodo "orderBy" che accetta il parametro per determinare in quale ordine ordinarlo. Puoi usarlo come

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

Per qualche motivo, non è documentato nei documenti del sito Web.


Penso che tu abbia confuso il trattino basso con lodash . Solo quest'ultimo ha la funzione orderBy menzionata .
Thomas Marti,

Sì, mia cattiva. Aggiornerà la risposta. Grazie per la correzione :)
Minkesh Jain,

orderBy, super utile! Molto meglio dell'uso inverso, poiché conserva la proprietà di ordinamento stabile che sto cercando.
Flimm,

Non funziona per me per qualche motivo upadte: its lodash (
aleXela

0

Underscore Mixins

Estendendo la risposta di @emil_lundberg, puoi anche scrivere un "mixin" se stai usando Underscore per creare una funzione personalizzata per l'ordinamento se è un tipo di ordinamento che potresti ripetere in un'applicazione da qualche parte.

Ad esempio, forse hai un controller o visualizzi i risultati dell'ordinamento con l'ordinamento di "ASC" o "DESC" e vuoi passare da quell'ordinamento, potresti fare qualcosa del genere:

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

Esempio di utilizzo

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

Ecco un JSFiddle che lo dimostra: JSFiddle per SortBy Mixin

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.