Sortieren eines Arrays von Objekten nach zwei Eigenschaften

Lesezeit: 5 Minuten

Sortieren eines Arrays von Objekten nach zwei Eigenschaften
Sven Kannenberg

Ich habe ein Array von Objekten, die ich nach zwei Eigenschaften sortieren möchte:

  1. ErinnerungZeitstempel
  2. Ä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.

  • 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

Sortieren eines Arrays von Objekten nach zwei Eigenschaften
RobG

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).

  • @Phrogz – eine absteigende Sortierung wird durch Ändern erreicht a - b zu b - a. ISO8601 kurze Datumssortierung (z. B. 20120412), lange Datumsangaben können vor der Subtraktion in Datumsobjekte konvertiert werden.

    – RobG

    15. April 2012 um 6:19 Uhr

  • Ich liebe diese Lösung, wünschte, ich könnte mehr als +1 tun 🙂

    – Hanna

    3. August 2016 um 12:16 Uhr

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:

Sortieren eines Arrays von Objekten nach zwei Eigenschaften
Phrogz

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

997190cookie-checkSortieren eines Arrays von Objekten nach zwei Eigenschaften

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy