Sortieren von (mehr) komplexen Arrays von Objekten
Da Sie wahrscheinlich auf komplexere Datenstrukturen wie dieses Array stoßen, würde ich die Lösung erweitern.
TL;DR
Sind mehr steckbare Version basierend auf @ege-Özcan ist sehr schön 回答 .
Problema
Ich bin auf das folgende Problem gestoßen und konnte es nicht ändern. Ich wollte auch nicht, um das Objekt vorübergehend zu glätten. Auch wollte ich nicht underscore / lodash verwenden, vor allem aus Gründen der Leistung und der Spaß, es selbst zu implementieren.
var People = [
{Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"},
{Name: {name: "AAA", surname: "ZZZ"}, Middlename:"Abrams"},
{Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"}
];
Ziel
Das Ziel ist es, sie in erster Linie zu sortieren nach People.Name.name
und in zweiter Linie durch People.Name.surname
Hindernisse
In der Basislösung wird nun die Klammerschreibweise verwendet, um die Eigenschaften zu berechnen, nach denen dynamisch sortiert werden soll. Hier müssten wir jedoch die Klammerschreibweise ebenfalls dynamisch konstruieren, da Sie etwas wie People['Name.name']
funktionieren würde - was nicht der Fall ist.
Einfach tun People['Name']['name']
ist dagegen statisch und erlaubt nur die Abwärtsbewegung auf der n -Stufe.
Lösung
Der Hauptzusatz besteht hier darin, den Objektbaum abwärts zu gehen und den Wert des letzten Blattes, das Sie angeben müssen, sowie jedes dazwischenliegende Blatt zu bestimmen.
var People = [
{Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"},
{Name: {name: "AAA", surname: "ZZZ"}, Middlename:"Abrams"},
{Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"}
];
People.sort(dynamicMultiSort(['Name','name'], ['Name', '-surname']));
// Results in...
// [ { Name: { name: 'AAA', surname: 'ZZZ' }, Middlename: 'Abrams' },
// { Name: { name: 'Name', surname: 'Surname' }, Middlename: 'JJ' },
// { Name: { name: 'Name', surname: 'AAA' }, Middlename: 'Wars' } ]
// same logic as above, but strong deviation for dynamic properties
function dynamicSort(properties) {
var sortOrder = 1;
// determine sort order by checking sign of last element of array
if(properties[properties.length - 1][0] === "-") {
sortOrder = -1;
// Chop off sign
properties[properties.length - 1] = properties[properties.length - 1].substr(1);
}
return function (a,b) {
propertyOfA = recurseObjProp(a, properties)
propertyOfB = recurseObjProp(b, properties)
var result = (propertyOfA < propertyOfB) ? -1 : (propertyOfA > propertyOfB) ? 1 : 0;
return result * sortOrder;
};
}
/**
* Takes an object and recurses down the tree to a target leaf and returns it value
* @param {Object} root - Object to be traversed.
* @param {Array} leafs - Array of downwards traversal. To access the value: {parent:{ child: 'value'}} -> ['parent','child']
* @param {Number} index - Must not be set, since it is implicit.
* @return {String|Number} The property, which is to be compared by sort.
*/
function recurseObjProp(root, leafs, index) {
index ? index : index = 0
var upper = root
// walk down one level
lower = upper[leafs[index]]
// Check if last leaf has been hit by having gone one step too far.
// If so, return result from last step.
if (!lower) {
return upper
}
// Else: recurse!
index++
// HINT: Bug was here, for not explicitly returning function
// https://stackoverflow.com/a/17528613/3580261
return recurseObjProp(lower, leafs, index)
}
/**
* Multi-sort your array by a set of properties
* @param {...Array} Arrays to access values in the form of: {parent:{ child: 'value'}} -> ['parent','child']
* @return {Number} Number - number for sort algorithm
*/
function dynamicMultiSort() {
var args = Array.prototype.slice.call(arguments); // slight deviation to base
return function (a, b) {
var i = 0, result = 0, numberOfProperties = args.length;
// REVIEW: slightly verbose; maybe no way around because of `.sort`-'s nature
// Consider: `.forEach()`
while(result === 0 && i < numberOfProperties) {
result = dynamicSort(args[i])(a, b);
i++;
}
return result;
}
}
Beispiel
Arbeitsbeispiel auf JSBin
8 Stimmen
Mit diesem Skript können Sie genau das tun, es sei denn, Sie möchten Ihre eigene Vergleichsfunktion oder Ihren eigenen Sortierer schreiben: thomasfrank.se/sortierung_der-dinge.html
0 Stimmen
Der schnellste Weg ist die Verwendung der isomorphen sort-array Modul, das nativ sowohl im Browser als auch im Node funktioniert und jede Art von Eingabe, berechnete Felder und benutzerdefinierte Sortierreihenfolgen unterstützt.
0 Stimmen
Function compare( a, b ) { if ( a.last_nom < b.last_nom ){ return -1; } if ( a.last_nom > b.last_nom ){ return 1; } return 0; } objs.sort( compare );
0 Stimmen
Objs.sort((a,b) => (a.last_nom > b.last_nom) ? 1 : ((b.letzte_Nom > a.letzte_Nom) ? -1 : 0))
0 Stimmen
@artem Bitte reichen Sie Ihre eigene Antwort ein.
2 Stimmen
@RobertTalada das ist meine Antwort stackoverflow.com/a/67021585/7012450
0 Stimmen
Das Muster für Sortierung nach Eigenschaften lexikographisch ist
objs.sort((a, b) => a.last_nom.localeCompare(b.last_nom))
. Zum Sortieren numerisch verwendena.prop - b.prop
. Um absteigend statt aufsteigend zu sortieren, negieren Sie den Rückgabewert (z. B.b.last_nom.localeCompare(a.last_nom)
anstelle vona.last_nom.localeCompare(b.last_nom)
). Zum Sortieren nach mehrere Objekte , Kette andere Sorten mit||
z.B.b.someNumber - a.someNumber || a.someString.localeCompare(b.someString)
.2 Stimmen
Groß-/Kleinschreibung beachten oder nicht beachten?