Frage Wie sortiere ich ein assoziatives Array nach seinen Werten in Javascript?


Ich habe das assoziative Array:

array["sub2"] = 1;
array["sub0"] = -1;
array["sub1"] = 0;
array["sub3"] = 1;
array["sub4"] = 0;

Was ist der eleganteste Weg, um nach seinen Werten zu sortieren (absteigend), wobei das Ergebnis ein Array mit den entsprechenden Indizes in dieser Reihenfolge wäre:

sub2, sub3, sub1, sub4, sub0?

75
2018-03-04 22:17


Ursprung


Antworten:


Javascript hat keine "assoziativen Arrays", wie Sie es sich vorstellen. Stattdessen haben Sie einfach die Möglichkeit, Objekteigenschaften mithilfe der arrayähnlichen Syntax (wie in Ihrem Beispiel) festzulegen, sowie die Möglichkeit, über die Eigenschaften eines Objekts zu iterieren.

Das Ergebnis ist, dass es keine Garantie für die Auftrag in dem du über die Eigenschaften iterierst, also gibt es nichts wie eine Art für sie. Stattdessen müssen Sie Ihre Objekteigenschaften in ein "echtes" Array konvertieren (was die Reihenfolge garantiert). Hier ist ein Code-Snippet, um ein Objekt in ein Array von Zwei-Tupeln (Zwei-Element-Arrays) umzuwandeln, es wie beschrieben zu sortieren und dann darüber zu iterieren:

var tuples = [];

for (var key in obj) tuples.push([key, obj[key]]);

tuples.sort(function(a, b) {
    a = a[1];
    b = b[1];

    return a < b ? -1 : (a > b ? 1 : 0);
});

for (var i = 0; i < tuples.length; i++) {
    var key = tuples[i][0];
    var value = tuples[i][1];

    // do something with key and value
}

Sie können es natürlicher finden, dies in eine Funktion einzubinden, die einen Callback übernimmt:

function bySortedValue(obj, callback, context) {
  var tuples = [];

  for (var key in obj) tuples.push([key, obj[key]]);

  tuples.sort(function(a, b) {
    return a[1] < b[1] ? 1 : a[1] > b[1] ? -1 : 0
  });

  var length = tuples.length;
  while (length--) callback.call(context, tuples[length][0], tuples[length][1]);
}

bySortedValue({
  foo: 1,
  bar: 7,
  baz: 3
}, function(key, value) {
  document.getElementById('res').innerHTML += `${key}: ${value}<br>`
});
<p id='res'>Result:<br/><br/><p>


108
2018-03-04 22:31



Anstatt Sie auf die Semantik eines 'assoziativen Arrays' zu korrigieren, denke ich, dass Sie das wollen:

function getSortedKeys(obj) {
    var keys = []; for(var key in obj) keys.push(key);
    return keys.sort(function(a,b){return obj[b]-obj[a]});
}

Sie deponieren ein Objekt (wie Ihres) und erhalten ein Array der Schlüssel - eh properties - zurück, sortiert absteigend nach dem (numerischen) Wert der, wie, Werte des, eh, Objekts.

Dies funktioniert nur, wenn Ihre Werte numerisch sind. Tweek das kleine function(a,b) in dort, um den Sortiermechanismus zu ändern, um aufsteigend zu arbeiten oder für zu arbeiten string Werte (zum Beispiel). Links als Übung für den Leser.

EDIT: Leute upvoting diese Antwort, aber es ist wirklich alt. Bitte   überdenken Sie, warum Sie nicht nur verwenden Object.keys () heutzutage.


69
2017-08-04 20:25



Fortsetzung der Diskussion und andere Lösungen unter Wie sortiere ich ein (assoziatives) Array nach Wert? mit der besten Lösung (für meinen Fall) saml (unten zitiert).

Arrays können nur numerische Indizes haben. Sie müssten dies entweder als Objekt oder als Array von Objekten umschreiben.

var status = new Array();
status.push({name: 'BOB', val: 10});
status.push({name: 'TOM', val: 3});
status.push({name: 'ROB', val: 22});
status.push({name: 'JON', val: 7});

Wenn du das magst status.push Methode, Sie können es sortieren mit:

status.sort(function(a,b) {
    return a.val - b.val;
});

15
2017-10-08 23:27



In JavaScript gibt es eigentlich kein "assoziatives Array". Was Sie dort haben, ist nur ein einfaches altes Objekt. Sie arbeiten natürlich ähnlich wie assoziative Arrays, und die Schlüssel sind verfügbar, aber es gibt keine Semantik um die Reihenfolge der Schlüssel.

Sie könnten Ihr Objekt in ein Array von Objekten (Schlüssel / Wert-Paare) umwandeln und das sortieren:

function sortObj(object, sortFunc) {
  var rv = [];
  for (var k in object) {
    if (object.hasOwnProperty(k)) rv.push({key: k, value:  object[k]});
  }
  rv.sort(function(o1, o2) {
    return sortFunc(o1.key, o2.key);
  });
  return rv;
}

Dann würden Sie das mit einer Komparatorfunktion aufrufen.


5
2018-03-04 22:30



Hier ist eine Variante von Ben Blanks Antwort, wenn Sie Tupel nicht mögen.

Das spart dir ein paar Zeichen.

var keys = [];
for (var key in sortme) {
  keys.push(key);
}

keys.sort(function(k0, k1) {
  var a = sortme[k0];
  var b = sortme[k1];
  return a < b ? -1 : (a > b ? 1 : 0);
});

for (var i = 0; i < keys.length; ++i) {
  var key = keys[i];
  var value = sortme[key];
  // Do something with key and value.
}

4
2018-05-02 18:21



Keine unnötige Komplikation erforderlich ...

function sortMapByValue(map)
{
    var tupleArray = [];
    for (var key in map) tupleArray.push([key, map[key]]);
    tupleArray.sort(function (a, b) { return a[1] - b[1] });
    return tupleArray;
}

4
2018-01-10 05:07



Ich benutze $ .jedes von jquery, aber Sie können es mit einer for-Schleife machen, eine Verbesserung ist das:

        //.ArraySort(array)
        /* Sort an array
         */
        ArraySort = function(array, sortFunc){
              var tmp = [];
              var aSorted=[];
              var oSorted={};

              for (var k in array) {
                if (array.hasOwnProperty(k)) 
                    tmp.push({key: k, value:  array[k]});
              }

              tmp.sort(function(o1, o2) {
                    return sortFunc(o1.value, o2.value);
              });                     

              if(Object.prototype.toString.call(array) === '[object Array]'){
                  $.each(tmp, function(index, value){
                      aSorted.push(value.value);
                  });
                  return aSorted;                     
              }

              if(Object.prototype.toString.call(array) === '[object Object]'){
                  $.each(tmp, function(index, value){
                      oSorted[value.key]=value.value;
                  });                     
                  return oSorted;
              }               
     };

Jetzt kannst du es tun

    console.log("ArraySort");
    var arr1 = [4,3,6,1,2,8,5,9,9];
    var arr2 = {'a':4, 'b':3, 'c':6, 'd':1, 'e':2, 'f':8, 'g':5, 'h':9};
    var arr3 = {a: 'green', b: 'brown', c: 'blue', d: 'red'};
    var result1 = ArraySort(arr1, function(a,b){return a-b});
    var result2 = ArraySort(arr2, function(a,b){return a-b});
    var result3 = ArraySort(arr3, function(a,b){return a>b});
    console.log(result1);
    console.log(result2);       
    console.log(result3);

1
2017-07-19 13:22



Nur so ist es da draußen und jemand sucht nach Tupel-basierten Arten. Dies vergleicht das erste Element des Objekts in Array, als das zweite Element und so weiter. d. h. im folgenden Beispiel wird zuerst mit "a" und dann mit "b" usw. verglichen.

let arr = [
    {a:1, b:2, c:3},
    {a:3, b:5, c:1},
    {a:2, b:3, c:9},
    {a:2, b:5, c:9},
    {a:2, b:3, c:10}    
]

function getSortedScore(obj) {
    var keys = []; 
    for(var key in obj[0]) keys.push(key);
    return obj.sort(function(a,b){
        for (var i in keys) {
            let k = keys[i];
            if (a[k]-b[k] > 0) return -1;
            else if (a[k]-b[k] < 0) return 1;
            else continue;
        };
    });
}

console.log(getSortedScore(arr))

OUPÜSSE

 [ { a: 3, b: 5, c: 1 },
  { a: 2, b: 5, c: 9 },
  { a: 2, b: 3, c: 10 },
  { a: 2, b: 3, c: 9 },
  { a: 1, b: 2, c: 3 } ]

0
2018-06-27 10:45



Der beste Ansatz für den konkreten Fall ist meiner Meinung nach dieser Normalpike empfohlen. Eine kleine Verbesserung würde ich vorschlagen, dass in modernen Browsern funktioniert:

// aao is the "associative array" you need to "sort"
Object.keys(aao).sort(function(a,b){return aao[b]-aao[a]});

Dies könnte leicht zutreffen und im konkreten Fall gut funktionieren, so dass Sie Folgendes tun können:

let aoo={};
aao["sub2"]=1;
aao["sub0"]=-1;
aao["sub1"]=0;
aao["sub3"]=1;
aao["sub4"]=0;

let sk=Object.keys(aao).sort(function(a,b){return aao[b]-aao[a]});

// now you can loop using the sorted keys in `sk` to do stuffs
for (let i=sk.length-1;i>=0;--i){
 // do something with sk[i] or aoo[sk[i]]
}

Außerdem biete ich hier eine eher "generische" Funktion an, die Sie verwenden können, um selbst in einem größeren Bereich von Situationen zu sortieren, und die die Verbesserung, die ich gerade vorgeschlagen habe, mit den Ansätzen der Antworten mischt Ben leer (Sortierung auch String-Werte) und Papst Johannes Paul II (Sortieren nach spezifischem Objektfeld / Eigenschaft) und lässt Sie entscheiden, ob Sie eine Aszendenten- oder Nachkommen-Reihenfolge wollen, hier ist es:

// aao := is the "associative array" you need to "sort"
// comp := is the "field" you want to compare or "" if you have no "fields" and simply need to compare values
// intVal := must be false if you need comparing non-integer values
// desc := set to true will sort keys in descendant order (default sort order is ascendant)
function sortedKeys(aao,comp="",intVal=false,desc=false){
  let keys=Object.keys(aao);
  if (comp!="") {
    if (intVal) {
      if (desc) return keys.sort(function(a,b){return aao[b][comp]-aao[a][comp]});
      else return keys.sort(function(a,b){return aao[a][comp]-aao[a][comp]});
    } else {
      if (desc) return keys.sort(function(a,b){return aao[b][comp]<aao[a][comp]?1:aao[b][comp]>aao[a][comp]?-1:0});
      else return keys.sort(function(a,b){return aao[a][comp]<aao[b][comp]?1:aao[a][comp]>aao[b][comp]?-1:0});
    }
  } else {
    if (intVal) {
      if (desc) return keys.sort(function(a,b){return aao[b]-aao[a]});
      else return keys.sort(function(a,b){return aao[a]-aao[b]});
    } else {
      if (desc) return keys.sort(function(a,b){return aao[b]<aao[a]?1:aao[b]>aao[a]?-1:0});
      else return keys.sort(function(a,b){return aao[a]<aao[b]?1:aao[a]>aao[b]?-1:0});
    }
  }
}

Sie können die Funktionen testen, indem Sie etwas wie den folgenden Code versuchen:

let items={};
items['Edward']=21;
items['Sharpe']=37;
items['And']=45;
items['The']=-12;
items['Magnetic']=13;
items['Zeros']=37;
//equivalent to:
//let items={"Edward": 21, "Sharpe": 37, "And": 45, "The": -12, ...};

console.log("1: "+sortedKeys(items));
console.log("2: "+sortedKeys(items,"",false,true));
console.log("3: "+sortedKeys(items,"",true,false));
console.log("4: "+sortedKeys(items,"",true,true));
/* OUTPUT
1: And,Sharpe,Zeros,Edward,Magnetic,The
2: The,Magnetic,Edward,Sharpe,Zeros,And
3: The,Magnetic,Edward,Sharpe,Zeros,And
4: And,Sharpe,Zeros,Edward,Magnetic,The
*/

items={};
items['k1']={name:'Edward',value:21};
items['k2']={name:'Sharpe',value:37};
items['k3']={name:'And',value:45};
items['k4']={name:'The',value:-12};
items['k5']={name:'Magnetic',value:13};
items['k6']={name:'Zeros',value:37};

console.log("1: "+sortedKeys(items,"name"));
console.log("2: "+sortedKeys(items,"name",false,true));
/* OUTPUT
1: k6,k4,k2,k5,k1,k3
2: k3,k1,k5,k2,k4,k6
*/

Wie ich bereits sagte, können Sie über sortierte Schlüssel durchlaufen, wenn Sie Dinge tun müssen

let sk=sortedKeys(aoo);
// now you can loop using the sorted keys in `sk` to do stuffs
for (let i=sk.length-1;i>=0;--i){
 // do something with sk[i] or aoo[sk[i]]
}

Last but not least, einige nützliche Verweise auf Objekt.Schlüssel und Array.sort


0
2018-06-30 16:20