Comment puis-je faire un tri asc et desc en utilisant underscore.js?

166

J'utilise actuellement des underscorejs pour trier mon tri json. Maintenant, j'ai demandé à faire un tri ascendinget à l' descendingaide de underscore.js. Je ne vois rien de semblable dans la documentation. Comment puis-je atteindre cet objectif?

Rahul
la source
1
Veuillez ajouter un exemple de ce que vous triez et comment.
Jon
Que triez-vous? Nombres? Des cordes? Rendez-vous? Autre chose?
mu est trop court le
@muistooshort Je trie un tableau d'objets. La méthode sortBy convient donc parfaitement à mes critères de tri croissant, mais pas l'inverse.
Rahul
Si vous triez par un nombre, votre sortByfonction peut l'être, return -nmais cela ne fonctionnera pas pour les chaînes; d'où la question de savoir quels types de choses vous triez.
mu est trop court
2
Avec Lodash, vous pouvez utiliser des raccourcis comme _.sortBy([1,4,3,2]).reverse()ou _.chain([1,4,3,2]).sortBy().reverse().value()si vous ne voulez pas utiliser le reverse()prototype d'Array.
GFoley83

Réponses:

363

Vous pouvez utiliser .sortBy, il renverra toujours une liste ascendante :

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

Mais vous pouvez utiliser la méthode .reverse pour le faire descendre :

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

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

Ou lorsque vous traitez avec des nombres, ajoutez un signe négatif au retour pour descendre la liste:

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

Sous le capot .sortByutilise le intégré .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
la source
9
Dernière solution, c'est-à-dire ajouter un signe négatif au nombre renvoyé est parfait.
vinesh
Pourquoi pensez-vous que c'est du genre à bulles? Sous le capot, les .sortBy()appels intégrés Array.sort(), dont l'algorithme appartient aux fournisseurs de navigateurs, mais il est peu probable que le tri par bulles soit leur choix.
Rene Saarsoo
Cela n'augmente-t-il pas la complexité du temps? Cela provoque le tri de la liste deux fois.
user1477388
@ user1477388 Je ne suis pas sûr de ce que vous entendez par trié deux fois?
andlrc
@andlrc Donc, lorsque vous appelez _.sortBy(arr, function), je suppose qu'il boucle sur chaque élément et exécute une logique pour renvoyer le tableau trié. Ensuite, lorsque vous l'appelez, Array.prototype.reverse()il boucle probablement à nouveau chaque élément et exécute une logique pour retourner le tableau inversé. Par conséquent, vous bouclez le tableau deux fois.
user1477388
57

L'ordre décroissant utilisant le trait de soulignement peut être effectué en multipliant la valeur de retour par -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 vous triez par chaînes et non par nombres, vous pouvez utiliser la méthode charCodeAt () pour obtenir la valeur unicode.

//Descending Order Strings:
_.sortBy(['a', 'b', 'c'], function(s){ 
    return s.charCodeAt() * -1;
});
jEremyB
la source
3
J'essaie de trier par ordre alphabétique - multiplier par -1 n'est pas une opération valide. :)
rythos42
C'est un cas d'utilisation intéressant mais non spécifié dans la question. Cependant, multiplier une chaîne par -1 est une opération valide. Il renvoie NaN, qui est un résultat valide.
jEremyB
1
n'oubliez pas de réattribuer le tableau aussi! SOME_ARR = _.sortBy (SOME_ARR, fonction (num) {SOME_FUNC ...});
aqm
4
charCodeAt sera « retour Unicode du caractère à l'index spécifié dans une chaîne » de sorte qu'il peut être utilisé pour trier par des personnages dans une chaîne, mais comme le montre qu'il ne pas « sorte par chaîne » trie par un caractère dans la chaîne
Anthony
2
Cela ne trie que par le premier caractère et il est sensible à la casse.
aidan
50

La méthode inverse du prototype Array modifie le tableau et lui renvoie une référence, ce qui signifie que vous pouvez le faire:

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

En outre, la documentation de soulignement se lit comme suit:

De plus, les méthodes du prototype Array sont envoyées par proxy via l'objet Underscore chaîné, vous pouvez donc insérer un reverseou un pushdans votre chaîne et continuer à modifier le tableau.

ce qui signifie que vous pouvez également utiliser .reverse()lors du chaînage:

var sortedDescAndFiltered = _.chain(collection)
    .sortBy('propertyName')
    .reverse()
    .filter(_.property('isGood'))
    .value();
Emil Lundberg
la source
C'est de loin la méthode la plus simple pour le tri inversé / décroissant lorsqu'il s'agit de la plupart des cas d'utilisation simples.
Dan Atkinson
2
Pour faire un tri alphabétique insensible à la casse:_.sortBy(collection, item => item. propertyName.toLowerCase());
XåpplI'-I0llwlg'I -
cela ne fonctionne pas s'il y a des nombres négatifs dans le tableau.
Shruti Kapoor
@ShrutiKapoor Oui, c'est vrai. Pourquoi pas?
Emil Lundberg
5
En termes de performances, il serait préférable d'appliquer d'abord le filtre, puis de trier les valeurs (restantes).
Saran
12

Semblable à la bibliothèque Underscore, il existe une autre bibliothèque appelée «lodash» qui a une méthode «orderBy» qui prend le paramètre pour déterminer dans quel ordre le trier. Vous pouvez l'utiliser comme

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

Pour une raison quelconque, il n'est pas documenté sur les documents du site Web.

Minkesh Jain
la source
Je pense que vous avez confondu le soulignement avec le lodash . Seul ce dernier a la fonction orderBy mentionnée .
Thomas Marti
Ouais, mon mal. Mettra à jour la réponse. Merci d'avoir corrigé :)
Minkesh Jain
orderBy, super utile! Bien mieux que d'utiliser le reverse, car il préserve la propriété de tri stable que je recherche.
Flimm
Ne fonctionne pas pour moi pour une raison quelconque upadte: its lodash (
aleXela
0

Souligner les mixins

En prolongeant la réponse de @ emil_lundberg, vous pouvez également écrire un "mixin" si vous utilisez Underscore pour créer une fonction personnalisée pour le tri s'il s'agit d'une sorte de tri que vous pourriez répéter dans une application quelque part.

Par exemple, vous avez peut-être un contrôleur ou affichez les résultats de tri avec l'ordre de tri "ASC" ou "DESC", et que vous souhaitez basculer entre ces types, vous pouvez faire quelque chose comme ceci:

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

Exemple d'utilisation

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

Voici un JSFiddle démontrant ceci: JSFiddle pour SortBy Mixin

RoboBear
la source