Ich habe ein Array von Objekten, die ich nach zwei Eigenschaften sortieren möchte:
- ErinnerungZeitstempel
- Änderungszeitstempel
Sortierreihenfolge: absteigend
Das Sortieren dieses Objekts nach einer Eigenschaft ist nicht das Problem, aber in diesem Fall habe ich keine Ahnung, wie es funktioniert.
Unter der Annahme, dass die Zeitstempel selbst in Ordnung sind (z. B. ISO8601 und dieselbe Zeitzone), versuchen Sie Folgendes:
myArray.sort(function(a,b) {
var x = a.RemindingTimestamp - b.RemindingTimestamp;
return x == 0? a.ModificationTimestamp - b.ModificationTimestamp : x;
}
Bearbeiten – Antwort auf Kommentare
Eine absteigende Sortierung wird erreicht, indem die Reihenfolge der Subtraktion geändert oder das Ergebnis mit -1 multipliziert wird. Daten, die nicht sortiert werden, weil sie nicht subtrahieren (z. B. 2012-04-12), können behandelt werden, indem sie zuerst in Daten konvertiert werden, z
// Convert ISO8601 date string to date object
// Assuming date is ISO8601 long format, ignores timezone
function toDate(s) {
var bits = s.split(/[-T :]/);
var d = new Date(bits[0], bits[1]-1, bits[2]);
d.setHours(bits[3], bits[4], parseFloat(bits[5]));
return d;
}
// Source data, should end up sorted per n
var myArray = [
{RemindingTimestamp: '2012-04-15T23:15:12Z',
ModificationTimestamp: '2012-04-15T23:15:12Z', n: 4},
{RemindingTimestamp: '2012-04-12T23:15:12Z',
ModificationTimestamp: '2012-04-12T23:15:12Z', n: 1},
{RemindingTimestamp: '2012-04-12T23:15:12Z',
ModificationTimestamp: '2012-04-13T23:15:12Z', n: 2},
{RemindingTimestamp: '2012-04-12T23:15:12Z',
ModificationTimestamp: '2012-04-13T23:15:14Z', n: 3}
];
// Sort it
myArray.sort(function(a,b) {
var x = toDate(a.RemindingTimestamp) - toDate(b.RemindingTimestamp);
return x? x : toDate(a.ModificationTimestamp) - toDate(b.ModificationTimestamp);
});
// Just to show the result
function sa(o) {
var result = [], t;
for (var i=0; i<o.length; i++) {
t = o[i];
result.push(t.n);
}
alert(result);
}
sa(myArray); // 1,2,3,4
Die Konvertierung der Datumszeichenfolge in das Datumsobjekt kann bei Bedarf erweitert werden, um die Zeitzone zu verarbeiten (nur für ISO8601-kompatible Zeichenfolgen sind diejenigen, die Zeitzonenabkürzungen anstelle des tatsächlichen Offsets verwenden, unzuverlässig).
function compareObject(obj1, obj2){
if(obj1.RemindingTimestamp > obj2.RemindingTimestamp)
return - 1;
if(obj2.RemindingTimestamp > obj1.RemindingTimestamp)
return 1;
// obj1.RemindingTimestamp == obj2.RemindingTimestamp
if(obj1.ModificationTimestamp > obj2.ModificationTimestamp)
return -1;
if(obj2.ModificationTimestamp > obj1.ModificationTimestamp)
return 1;
return 0;
}
myObjects.sort(compareObject);
JSFiddle-Demo
Ressourcen:
Benutzerdefinierte Komparatoren haben die Form:
myArray.sort(function(a,b){
var m1=a1.RemindingTimestamp,
m2=a2.RemindingTimestamp,
n1=a1.ModificationTimestamp,
n2=a2.ModificationTimestamp;
return m1<m2 ? -1 : m1>m2 ? 1 :
n1<n2 ? -1 : n1>n2 ? 1 : 0;
});
Tauschen Sie für absteigende Sortierung die <
und >
(oder tauschen 1
und -1
).
Während Sie jedes Mal, wenn Sie dies benötigen, Ihren eigenen benutzerdefinierten Komparator erstellen können, habe ich eine Methode entwickelt, die explizit für das einfache Sortieren nach mehreren Kriterien entwickelt wurde, indem Sie a verwenden Schwartzsche Transformation (was unter Umständen schneller, aber speicherhungriger sein kann): http://phrogz.net/js/Array.prototype.sortBy.js
Zusamenfassend:
myArray.sortBy(function(obj){
return [obj.RemindingTimestamp, obj.ModificationTimestamp];
}).reverse();
Die reverse
ist da, da du erwähnt hast, dass du eine absteigende Sortierung wolltest. Wenn beides RemindingTimestamp
und ModificationTimestamp
Zahlen sind, könnten Sie alternativ Folgendes tun:
myArray.sortBy(function(obj){
return [-obj.RemindingTimestamp, -obj.ModificationTimestamp];
});
Hier ist der Code, der hinzufügt sortBy
zu Arrays:
(function(){
// Extend Arrays in a safe, non-enumerable way
if (typeof Object.defineProperty === 'function'){
// Guard against IE8's broken defineProperty
try{Object.defineProperty(Array.prototype,'sortBy',{value:sb}); }catch(e){}
}
// Fall back to an enumerable implementation
if (!Array.prototype.sortBy) Array.prototype.sortBy = sb;
function sb(f){
for (var i=this.length;i;){
var o = this[--i];
this[i] = [].concat(f.call(o,o,i),o);
}
this.sort(function(a,b){
for (var i=0,len=a.length;i<len;++i){
if (a[i]!=b[i]) return a[i]<b[i]?-1:1;
}
return 0;
});
for (var i=this.length;i;){
this[--i]=this[i][this[i].length-1];
}
return this;
}
})();
Hier sind einige weitere Beispiele aus der Dokumentation:
var a=[ {c:"GK",age:37}, {c:"ZK",age:13}, {c:"TK",age:14}, {c:"AK",age:13} ];
a.sortBy( function(){ return this.age } );
--> [ {c:"ZK",age:13}, {c:"AK",age:13}, {c:"TK",age:14}, {c:"GK",age:37} ]
a.sortBy( function(){ return [this.age,this.c] } );
--> [ {c:"AK",age:13}, {c:"ZK",age:13}, {c:"TK",age:14}, {c:"GK",age:37} ]
a.sortBy( function(){ return -this.age } );
--> [ {c:"GK",age:37}, {c:"TK",age:14}, {c:"ZK",age:13}, {c:"AK",age:13} ]
var n=[ 1, 99, 15, "2", "100", 3, 34, "foo", "bar" ];
n.sort();
--> [ 1, "100", 15, "2", 3, 34, 99, "bar", "foo" ]
n.sortBy( function(){ return this*1 } );
--> [ "foo", "bar", 1, "2", 3, 15, 34, 99, "100" ]
n.sortBy( function(o){ return [typeof o,this] } );
--> [1, 3, 15, 34, 99, "100", "2", "bar", "foo"]
n.sortBy(function(o){ return [typeof o, typeof o=="string" ? o.length : o] })
--> [1, 3, 15, 34, 99, "2", "100", "bar", "foo"]
Beachten Sie im letzten Beispiel, dass (typeof this)
ist zufällig nicht dasselbe wie
(typeof o)
; Weitere Informationen finden Sie in diesem Beitrag.
Unter der Annahme, dass beide Eigenschaften im selben sortierbaren Format vorliegen, ist hier eine weitere Möglichkeit der Tiefensortierung ES6
:
const comparingFunction = (a, b) => {
if (a.property1 < b.property1) {
return -1;
}
if (a.property1 > b.property1) {
return 1;
}
if (a.property1 == b.property1) {
if (a.property2 < b.property2) {
return -1;
}
if (a.property2 > b.property2) {
return 1;
}
return 0;
}
};
myArrayOfObjects.sort(comparingFunction);
Hoffe es hilft jemandem.
Andere Weg
function sortBy(ar) {
return ar.sort((a, b) => a.RemindingTimestamp === b.RemindingTimestamp ?
a.ModificationTimestamp.toString().localeCompare(b.ModificationTimestamp) :
a.RemindingTimestamp.toString().localeCompare(b.RemindingTimestamp));
}
Vergleichen Sie die erste Eigenschaft. Wenn der Eigenschaftswert für zwei Elemente gleich ist, vergleichen Sie nur die zweite Eigenschaft. (Haben Sie noch nie ein Kartenspiel sortiert?)
– Spitze
14. April 2012 um 13:05 Uhr
Was sind die Arten dieser Eigenschaften? Zahlen, Zeichenfolgen oder Daten?
– Phrogz
14. April 2012 um 15:25 Uhr