¿Cómo puedo hacer una ordenación asc y desc usando underscore.js?

166

Actualmente estoy usando underscorejs para ordenar mi ordenación json. Ahora he pedido hacer ascendingy descendingordenar usando underscore.js. No veo nada relacionado con lo mismo en la documentación. ¿Cómo puedo conseguir esto?

Rahul
fuente
1
Agregue un ejemplo de lo que está ordenando y cómo.
Jon
Que estas clasificando ¿Números? ¿Instrumentos de cuerda? ¿Fechas? ¿Algo más?
mu es demasiado corto
@muistooshort Estoy ordenando una serie de objetos. Entonces, el método sortBy se adapta perfectamente a mis criterios para la clasificación ascendente, pero no al revés.
Rahul
Si está ordenando por un número, entonces su sortByfunción puede ser return -npero eso no funcionará para las cadenas; de ahí la pregunta sobre qué tipo de cosas estás ordenando.
mu es demasiado corto el
2
Con Lodash puedes usar taquigrafía _.sortBy([1,4,3,2]).reverse()o _.chain([1,4,3,2]).sortBy().reverse().value()si no quieres usar el reverse()prototipo de Array.
GFoley83

Respuestas:

363

Puede usar .sortBy, siempre devolverá una lista ascendente :

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

Pero puedes usar el método .reverse para que descienda :

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

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

O cuando se trata de números, agregue un signo negativo al retorno para descender la lista:

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

Debajo del capó se .sortByutiliza el incorporado .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
fuente
9
La última solución, es decir, agregar un signo negativo al número devuelto es perfecto.
vinesh
¿Por qué crees que es una especie de burbuja? Under the hood .sortBy()llama a las funciones integradas Array.sort(), cuyo algoritmo depende de los proveedores de navegadores, pero es muy poco probable que el tipo de burbuja sea su elección.
Rene Saarsoo
¿No aumenta esto la complejidad del tiempo? Hace que la lista se ordene dos veces.
user1477388
@ user1477388 No estoy seguro de lo que quieres decir con ordenado dos veces.
andlrc
@andlrc Entonces, cuando llamas _.sortBy(arr, function), supongo que recorre cada elemento y ejecuta cierta lógica para devolver la matriz ordenada. Luego, cuando lo llame Array.prototype.reverse(), probablemente repita cada elemento nuevamente y ejecute algo de lógica para devolver la matriz invertida. Por lo tanto, está repitiendo la matriz dos veces.
user1477388
57

El orden descendente con guión bajo se puede hacer multiplicando el 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]

Si está ordenando por cadenas, no por números, puede usar el método charCodeAt () para obtener el valor Unicode.

//Descending Order Strings:
_.sortBy(['a', 'b', 'c'], function(s){ 
    return s.charCodeAt() * -1;
});
jEremyB
fuente
3
Estoy tratando de ordenar alfabéticamente: multiplicar por -1 no es una operación válida. :)
rythos42
Vale la pena usarlo, pero no se especifica en la pregunta. Sin embargo, multiplicar una cadena por -1 es una operación válida. Devuelve NaN, que es un resultado válido.
jEremyB
1
¡recuerda asignar la matriz también! SOME_ARR = _.sortBy (SOME_ARR, function (num) {SOME_FUNC ...});
aqm
44
charCodeAt "devolverá el Unicode del carácter en el índice especificado en una cadena" para que pueda usarse para ordenar por caracteres en una cadena, pero como se muestra no "ordena por cadena", ordena por un carácter en la cadena
Anthony
2
Esto solo se ordena por el primer carácter, y distingue entre mayúsculas y minúsculas.
aidan
50

El método inverso del prototipo de matriz modifica la matriz y le devuelve una referencia, lo que significa que puede hacer esto:

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

Además, la documentación de subrayado dice:

Además, los métodos del prototipo de matriz se representan mediante el objeto subrayado encadenado, por lo que puede deslizar a reverseo a pushen su cadena y continuar modificando la matriz.

lo que significa que también puedes usar .reverse()mientras encadenas:

var sortedDescAndFiltered = _.chain(collection)
    .sortBy('propertyName')
    .reverse()
    .filter(_.property('isGood'))
    .value();
Emil Lundberg
fuente
Este es, por tarifa, el método más simple para la clasificación inversa / descendente cuando se trata de la mayoría de los casos de uso simples.
Dan Atkinson
2
Para hacer una ordenación alfabética sin distinción entre mayúsculas y minúsculas:_.sortBy(collection, item => item. propertyName.toLowerCase());
XåpplI'-I0llwlg'I -
Esto no funciona si hay números negativos en la matriz.
Shruti Kapoor
@ShrutiKapoor Sí, lo hace. ¿Por qué no lo haría?
Emil Lundberg el
55
En cuanto al rendimiento, sería preferible aplicar primero el filtro y luego ordenar (los restantes) valores.
Saran
12

De manera similar a la biblioteca Underscore, hay otra biblioteca llamada 'lodash' que tiene un método "orderBy" que toma el parámetro para determinar en qué orden ordenarlo. Puedes usarlo como

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

Por alguna razón, no está documentado en los documentos del sitio web.

Minkesh Jain
fuente
Creo que confundiste el guión bajo con lodash . Solo este último tiene la función orderBy mencionada .
Thomas Marti
Si, mi mal. Se actualizará la respuesta. Gracias por corregir :)
Minkesh Jain
orderBy, super útil! Mucho mejor que usar reverse, ya que conserva la propiedad de ordenación estable que estoy buscando.
Flimm
No funciona para mí por alguna razón upadte: its lodash (
aleXela
0

Subrayar mixins

Ampliando la respuesta de @ emil_lundberg, también puede escribir un "mixin" si está usando Underscore para hacer una función personalizada para ordenar si es un tipo de clasificación que podría repetir en una aplicación en alguna parte.

Por ejemplo, tal vez tenga un controlador o vea los resultados de clasificación con el orden de clasificación "ASC" o "DESC", y desee alternar entre ese tipo, podría hacer algo como esto:

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

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

Aquí hay un JSFiddle que demuestra esto: JSFiddle para SortBy Mixin

RoboBear
fuente