Como posso classificar asc e desc usando underscore.js?

166

Atualmente, estou usando underscorejs para classificar minha classificação de json. Agora eu ter pedido para fazer um ascendinge descendingclassificação usando underscore.js. Não vejo nada a respeito na documentação. Como posso conseguir isso?

Rahul
fonte
1
Por favor, adicione um exemplo do que você está classificando e como.
28413 Jon
O que você está classificando? Números? Cordas? Datas? Algo mais?
mu é muito curto
@muistooshort Estou classificando uma variedade de objetos. Portanto, o método sortBy se ajusta perfeitamente aos meus critérios para classificação crescente, mas não o contrário.
Rahul 01/03
Se você estiver classificando por um número, sua sortByfunção poderá ser, return -nmas isso não funcionará para strings; daí a pergunta sobre que tipo de coisas você está classificando.
mu é muito curto
2
Com o Lodash, você pode usar taquigrafia como _.sortBy([1,4,3,2]).reverse()ou _.chain([1,4,3,2]).sortBy().reverse().value()se não quiser usar o reverse()protótipo de Array.
GFoley83

Respostas:

363

Você pode usar .sortBy, ele sempre retornará uma lista crescente :

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

Mas você pode usar o método .reverse para fazê-lo descer :

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

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

Ou, ao lidar com números, adicione um sinal negativo ao retorno para descer a lista:

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

Sob o capô .sortByusa o construído em .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;
});
andlrc
fonte
9
Última solução, ou seja, adicionar sinal negativo ao num retornado é perfeito.
Vinesh
Por que você acha que é do tipo bolha? Sob o capô, .sortBy()chama-se built-in Array.sort(), cujo algoritmo depende dos fornecedores de navegadores, mas é improvável que a escolha de bolhas seja a sua escolha.
Rene Saarsoo
Isso não aumenta a complexidade do tempo? Faz com que a lista seja classificada duas vezes.
usar o seguinte comando
@ user1477388 Não sei o que você quer dizer com a classificação duas vezes?
andlrc
@andlrc Então, quando você chama _.sortBy(arr, function), presumo que ele faça um loop sobre cada item e execute alguma lógica para retornar a matriz classificada. Então, quando você chama Array.prototype.reverse(), provavelmente faz um loop sobre cada item novamente e executa alguma lógica para retornar a matriz invertida. Portanto, você está fazendo um loop na matriz duas vezes.
usar o seguinte comando
57

A ordem decrescente usando sublinhado pode ser feita multiplicando o valor de retorno por -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 você estiver classificando por seqüências de caracteres, não por números, poderá usar o método charCodeAt () para obter o valor unicode.

//Descending Order Strings:
_.sortBy(['a', 'b', 'c'], function(s){ 
    return s.charCodeAt() * -1;
});
jEremyB
fonte
3
Estou tentando classificar alfabeticamente - multiplicar por -1 não é uma operação válida. :)
rythos42
É um caso de uso que vale a pena, mas não especificado na pergunta. No entanto, multiplicar uma sequência por -1 é uma operação válida. Retorna NaN, que é um resultado válido.
jEremyB
1
lembre-se de atribuir a matriz de volta também! SOME_ARR = _.sortBy (SOME_ARR, função (num) {SOME_FUNC ...});
AQM
4
charCodeAt "retornará o Unicode do caractere no índice especificado em uma string" para que possa ser usado para classificar por caracteres em uma string, mas, como mostrado, ele não "classifica por string", ele classifica por um caractere na string
Anthony
2
Isso é classificado apenas pelo primeiro caractere e diferencia maiúsculas de minúsculas.
Aidan
50

O método reverso do protótipo Array modifica a matriz e retorna uma referência a ela, o que significa que você pode fazer isso:

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

Além disso, a documentação sublinhada diz:

Além disso, os métodos do protótipo Array são submetidos a proxy por meio do objeto Underscore em cadeia, para que você possa inserir reverseum ou um pushem sua cadeia e continuar modificando a matriz.

o que significa que você também pode usar .reverse()durante o encadeamento:

var sortedDescAndFiltered = _.chain(collection)
    .sortBy('propertyName')
    .reverse()
    .filter(_.property('isGood'))
    .value();
Emil Lundberg
fonte
Esse é, de fato, o método mais simples para classificação reversa / descendente quando se trata da maioria dos casos de uso simples.
Dan Atkinson
2
Para fazer uma classificação alfabética que não _.sortBy(collection, item => item. propertyName.toLowerCase());
diferencia
isso não funciona se houver números negativos na matriz.
Shruti Kapoor
@ShrutiKapoor Sim, sim. Por que não?
Emil Lundberg
5
Em termos de desempenho, seria preferível aplicar primeiro o filtro e depois classificar (os demais) valores.
21417 Saran
12

Semelhante à biblioteca de sublinhado, existe outra biblioteca chamada 'lodash' que possui um método "orderBy", que utiliza o parâmetro para determinar em qual ordem classificá-lo. Você pode usá-lo como

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

Por algum motivo, não está documentado nos documentos do site.

Minkesh Jain
fonte
Acho que você confundiu sublinhado com lodash . Somente o último possui a função orderBy mencionada .
9788 Thomas Thomson escreveu:
Sim, meu mal. Atualizará a resposta. Obrigado por corrigir :)
Minkesh Jain
orderBy, super útil! Muito melhor do que usar reverse, pois preserva a propriedade de classificação estável que estou procurando.
Flimm
Não está funcionando para mim por algum motivo upadte: seu lodash (
aleXela
0

Sublinhado Mixins

Estendendo-se à resposta de @ emil_lundberg, você também pode escrever um "mixin" se estiver usando o Underscore para criar uma função personalizada para classificação, se for um tipo de classificação que você poderá repetir em um aplicativo em algum lugar.

Por exemplo, talvez você tenha um controlador ou visualize os resultados da classificação com a ordem de classificação "ASC" ou "DESC" e deseje alternar entre essa classificação. Você pode fazer algo assim:

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

Exemplo de uso

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

Aqui está um JSFiddle demonstrando isso: JSFiddle para SortBy Mixin

RoboBear
fonte