Frage Sortieren Sie Array-Elemente und bewahren Sie die Reihenfolge derselben Elemente


Angenommen, ich habe dieses Array:

var array = [
  { name: "border-color", value: "#CCCCCC" },
  { name: "color", value: "#FFFFFF" },
  { name: "background-color", value: "rgb(0, 0, 0)" },
  { name: "background-color", value: "rgba(0, 0, 0, .5)" }
];

Und diese Funktion, um das Array nach Namen zu sortieren:

array.sort(function(a, b) {
  if (a.name < b.name) return -1;
  if (a.name > b.name) return 1;
  return 0;
});

Und ECMAScript Sprachspezifikationen, die mir das sagen:

Die Art ist nicht notwendigerweise stabil (dh Elemente, die vergleichen   gleich bleiben nicht unbedingt in ihrer ursprünglichen Reihenfolge).

Nach der Sortierung könnten die zwei Elemente mit Name = Hintergrundfarbe in beliebiger Reihenfolge erscheinen:

[
  { name: "background-color", value: "rgb(0, 0, 0)" },
  { name: "background-color", value: "rgba(0, 0, 0, .5)" },
  ...
]

Oder

[
  { name: "background-color", value: "rgba(0, 0, 0, .5)" },
  { name: "background-color", value: "rgb(0, 0, 0)" },
  ...
]

Wie kann ich das Array so sortieren, dass Elemente mit demselben Namen ihre relative Reihenfolge beibehalten? Ich würde lieber nichts hart codieren.


17
2017-07-03 20:15


Ursprung


Antworten:


Theoretisch vor dem Sortieren können Sie den Index im Array verfolgen und beim Sortieren berücksichtigen.

var sortArray = yourarray.map(function(data, idx){
    return {idx:idx, data:data}
})

sortArray.sort(function(a, b) {
  if (a.data.name < b.data.name) return -1;
  if (a.data.name > b.data.name) return 1;
  return a.idx - b.idx
});

var answer = sortArray.map(function(val){
    return val.data
});

17
2017-07-03 20:24



Da das Array den Referenztyp objet enthält, kann der Index des Elements in der Sortierfunktion bestimmt werden. So vermeiden wir die Karte vor und nach der Sortierung.

sortArray.sort((function(a, b) {
  if (a.name < b.name) return -1;
  if (a.name > b.name) return 1;
  return this.indexOf(a) - this.indexOf(b);
}).bind(sortArray));

1
2017-07-06 21:58



Fügen Sie dem Array ein zusätzliches Attribut hinzu: order

var array = [
    { name: "border-color", value: "#CCCCCC", order: 1 },
    { name: "color", value: "#FFFFFF", order: 2 },
    { name: "background-color", value: "rgb(0, 0, 0)", order: 3 },
    { name: "background-color", value: "rgba(0, 0, 0, .5)", order: 4 }
];

und ändern Sie dann die Sortierfunktion, um nach Reihenfolge zu sortieren, wenn der Name gleich ist:

array.sort(function(a, b) {
    if (a.name < b.name) return -1;
    if (a.name > b.name) return 1;
    if (a.name == b.name) {
        if(a.order > b.order) return -1; else return 1;
    }
});

Beachten Sie, dass das Vorzeichen der Rückgabe für den Auftrag angepasst werden muss, je nachdem, ob Sie es aufsteigend oder absteigend sortiert haben möchten (hier ging ich davon aus, dass Sie vom größten zum kleinsten sortieren, also geben Sie den mit der kleineren Reihenfolge zurück).


0
2017-07-03 20:25