Frage

Hier ist mein Array (Gawk -Skript):

myArray["peter"] = 32
myArray["bob"] = 5
myArray["john"] = 463
myArray["jack"] = 11

Nach der Sortierung brauche ich das folgende Ergebnis:

bob    5
jack   11
peter  32
john   463

Wenn ich "Asort" benutze, gehen Indizes verloren. Wie sortiert man nach Array -Wert, ohne Indizes zu verlieren? (Ich brauche geordnete Indizes basierend auf ihren Werten)

(Ich muss dieses Ergebnis nur mit awk/gawk, nicht mit Shell -Skript, Perl usw. erhalten)

Wenn mein Beitrag nicht klar genug ist, ist hier ein anderer Beitrag, der dasselbe Problem erklärt: http://www.experts-exchange.com/programming/glangages/scripting/shell/q_26626841.html )

Danke im Voraus

Aktualisieren :

Vielen Dank an euch beide, aber ich muss nach Werten sortieren, nicht nach Indizes (ich möchte geordnete Indizes gemäß ihren Werten).

Mit anderen Worten brauche ich dieses Ergebnis:

bob    5
jack   11
peter  32
john   463

nicht :

bob 5
jack 11
john 463
peter 32

(Ich stimme zu, mein Beispiel ist verwirrend, die gewählten Werte sind ziemlich schlecht)

Aus dem Code von Catcall habe ich eine schnelle Implementierung geschrieben, die funktioniert, aber es ist ziemlich hässlich (ich verkette Tasten und Werte, bevor ich während des Vergleichs sortieren und aufgeteilt habe). So sieht es aus:

function qsort(A, left, right,   i, last) {
  if (left >= right)
    return
  swap(A, left, left+int((right-left+1)*rand()))
  last = left
  for (i = left+1; i <= right; i++)
    if (getPart(A[i], "value") < getPart(A[left], "value"))
      swap(A, ++last, i)
  swap(A, left, last)
  qsort(A, left, last-1)
  qsort(A, last+1, right)
}

function swap(A, i, j,   t) {
  t = A[i]; A[i] = A[j]; A[j] = t
}

function getPart(str, part) {
  if (part == "key")
    return substr(str, 1, index(str, "#")-1)
  if (part == "value")
    return substr(str, index(str, "#")+1, length(str))+0
  return
}

BEGIN {  }
      {  }
END {

  myArray["peter"] = 32
  myArray["bob"] = 5
  myArray["john"] = 463
  myArray["jack"] = 11

  for (key in myArray)
    sortvalues[j++] = key "#" myArray[key]

  qsort(sortvalues, 0, length(myArray));

  for (i = 1; i <= length(myArray); i++)
    print getPart(sortvalues[i], "key"), getPart(sortvalues[i], "value")
}

Natürlich bin ich interessiert, wenn Sie etwas saubereres haben ...

Vielen Dank für Ihre Zeit

War es hilfreich?

Lösung

Bearbeiten:

Sortieren nach Werten

Oh! Um die zu sortieren Werte, Es ist ein kleiner Kludge, aber Sie können ein temporäres Array mit einer Verkettung der Werte und der Indizes des ursprünglichen Arrays als Indizes im Neuarray erstellen. Dann kannst du asorti() Das temporäre Array und teilen die verketteten Werte wieder in Indizes und Werte auf. Wenn Sie dieser verworrenen Beschreibung nicht folgen können, ist der Code viel einfacher zu verstehen. Es ist auch sehr kurz.

# right justify the integers into space-padded strings and cat the index
# to create the new index
for (i in myArray) tmpidx[sprintf("%12s", myArray[i]),i] = i
num = asorti(tmpidx)
j = 0
for (i=1; i<=num; i++) {
    split(tmpidx[i], tmp, SUBSEP)
    indices[++j] = tmp[2]  # tmp[2] is the name
}
for (i=1; i<=num; i++) print indices[i], myArray[indices[i]]

Bearbeiten 2:

Wenn Sie Gawk 4 haben, können Sie das Array nach Wertenreihenfolge durchqueren, ohne eine explizite Sorte durchzuführen:

#!/usr/bin/awk -f
BEGIN {
    myArray["peter"] = 32
    myArray["bob"] = 5
    myArray["john"] = 463
    myArray["jack"] = 11

    PROCINFO["sorted_in"] = "@val_num_asc"

    for (i in myArray) {
        {print i, myArray[i]}}
    }

 }

Es gibt Einstellungen für das Durchqueren nach Index oder Wert, aufsteigend oder absteigend und andere Optionen. Sie können auch eine benutzerdefinierte Funktion angeben.

Vorherige Antwort:

Sortieren nach Indizes

Wenn Sie einen awk haben, z. gawk 3.1.2 oder mehr, was unterstützt asorti():

#!/usr/bin/awk -f
BEGIN {
    myArray["peter"] = 32
    myArray["bob"] = 5
    myArray["john"] = 463
    myArray["jack"] = 11

    num = asorti(myArray, indices)
    for (i=1; i<=num; i++) print indices[i], myArray[indices[i]]
}

Wenn Sie nicht haben asorti():

#!/usr/bin/awk -f
BEGIN {
    myArray["peter"] = 32
    myArray["bob"] = 5
    myArray["john"] = 463
    myArray["jack"] = 11

    for (i in myArray) indices[++j] = i
    num = asort(indices)
    for (i=1; i<=num; i++) print i, indices[i], myArray[indices[i]]
}

Andere Tipps

Verwenden Sie den Befehl UNIX Sort
Erstellen Sie eine Eingabedatei mit von Comma getrennten Werte
Peter, 32
Jack, 11
John, 463
Bob, 5

Erstellen Sie eine sort.awk -Datei mit dem Code

BEGIN { FS=","; }
{
    myArray[$1]=$2;
}
END {
    for (name in myArray)
        printf ("%s,%d\n", name, myArray[name]) | "sort -t, -k2 -n"
}

Führen Sie das Programm aus, sollten Sie die Ausgabe geben
$ awk -f sort.awk Daten
Bob, 5
Jack, 11
Peter, 32
John, 463

PROCINFO["sorted_in"] = "@val_num_desc";

Verwenden Sie vor dem Iterieren eines Arrays die obige Anweisung. Aber es funktioniert in awk Version 4.0.1. Es funktioniert nicht in awk Version 3.1.7.

Ich bin mir nicht sicher, in welcher Zwischenversion sie vorgestellt wurde.

Und die einfache Antwort ...

function sort_by_myArray(i1, v1, i2, v2) {
    return myArray[i2] < myArray[i1];
}

BEGIN {
    myArray["peter"] = 32;
    myArray["bob"] = 5;
    myArray["john"] = 463;
    myArray["jack"] = 11;
    len = length(myArray);

    asorti(myArray, k, "sort_by_myArray");

    # Print result.
    for(n = 1; n <= len; ++n) {
            print k[n], myArray[k[n]]
    }
}

Die Autoren von Die awk -Programmiersprache zur Verfügung stellen Quicksort -Funktion, was online verfügbar ist.

Ich denke, du würdest so etwas tun.

END {
  for (key in myArray) {
    sortkeys[j++] = key;
  }
  qsort(sortkeys, 0, length(myArray));      # Not sure I got the args right.
  for (i = 1; i <= length(myArray); i++) {
    print sortkeys[i], myArray[sortkeys[i]];
  }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top