Je veux faire quelque chose comme ça:
var data = [
{
sortData: {a: 'a', b: 2}
},
{
sortData: {a: 'a', b: 1}
},
{
sortData: {a: 'b', b: 5}
},
{
sortData: {a: 'a', b: 3}
}
];
data = _.sortBy(data, ["sortData.a", "sortData.b"]);
_.map(data, function(element) {console.log(element.sortData.a + " " + element.sortData.b);});
Et le faire sortir ceci:
"a 1"
"a 2"
"a 3"
"b 5"
Malheureusement, cela ne fonctionne pas et le tableau reste trié dans sa forme d'origine. Cela fonctionnerait si les champs n'étaient pas imbriqués dans la sortData
. Comment utiliser lodash/underscore pour trier un tableau d'objets selon plusieurs champs imbriqués?
J'ai transformé cela en une demande de fonctionnalité lodash: https://github.com/lodash/lodash/issues/581
Il existe une méthode _.sortByAll
dans la version 3 de lodash:
https://github.com/lodash/lodash/blob/3.10.1/doc/README.md#_sortbyallcollection-iteratees
Lodash version 4, il a été unifié:
https://lodash.com/docs#sortBy
Une autre option serait de trier les valeurs vous-même:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
function compareValues(v1, v2) {
return (v1 > v2)
? 1
: (v1 < v2 ? -1 : 0);
};
var data = [
{ a: 2, b: 1 },
{ a: 2, b: 2 },
{ a: 1, b: 3 }
];
data.sort(function (x, y) {
var result = compareValues(x.a, y.a);
return result === 0
? compareValues(x.b, y.b)
: result;
});
// data after sort:
// [
// { a: 1, b: 3 },
// { a: 2, b: 1 },
// { a: 2, b: 2 }
// ];
Mise à jour: Voir les commentaires ci-dessous, ce n'est pas une bonne solution dans la plupart des cas.
Quelqu'un a gentiment répondu dans le numéro que j'ai créé . Voici sa réponse, en ligne:
_.sortBy(data, function(item) {
return [item.sortData.a, item.sortData.b];
});
Je n'avais pas réalisé que vous étiez autorisé à retourner un tableau de cette fonction. La documentation ne mentionne pas cela.
Si vous devez spécifier le sens du tri, vous pouvez utiliser _.orderBy
avec la syntaxe du tableau de fonctions de Lodash 4.x:
_.orderBy(data, [
function (item) { return item.sortData.a; },
function (item) { return item.sortData.b; }
], ["asc", "desc"]);
Cela triera d'abord en ordre croissant par la propriété a
, et pour les objets ayant la même valeur pour la propriété a
, les triera par ordre décroissant en propriété b
.
Cela fonctionne comme prévu lorsque les propriétés a
et b
ont des types différents.
Voici un exemple jsbin en utilisant cette syntaxe.
Le moyen simple et génial est:
_.sortBy(data, [function(item) {
return item.sortData.a;
}, function(item) {
return item.sortData.b;
}]);
Je l'ai trouvé en vérifiant le code source de lodash, il vérifie toujours la fonction un par un.
J'espère que cette aide.
Avec ES6 easy syntax et lodash
sortBy(item.sortData, (item) => (-item.a), (item) => (-item.b))
Si le problème est qu'un entier est converti en chaîne, ajoutez des zéros avant l'entier pour lui donner la même longueur que le plus long de la collection:
var maxLength = _.reduce(data, function(result, item) {
var bString = _.toString(item.sortData.b);
return result > bString.length ? result : bString.length;
}, 0);
_.sortBy(data, function(item) {
var bString = _.toString(item.sortData.b);
if(maxLength > bString.length) {
bString = [new Array(maxLength - bString.length + 1).join('0'), bString].join('');
}
return [item.sortData.a, bString];
});
Je pense que cela pourrait fonctionner dans la plupart des cas avec un trait de soulignement:
var properties = ["sortData.a", "sortData.b"];
data = _.sortBy(data, function (d) {
var predicate = '';
for (var i = 0; i < properties.length; i++)
{
predicate += (i == properties.length - 1
? 'd.' + properties[i]
: 'd.' + properties[i] + ' + ')
}
return eval(predicate)
});