2010-03-16 13 views
16

Ich habe ein assoziatives Array in awk, die wie folgt aufgefüllt wird:Sortieren ein assoziatives Array in awk

chr_count[$3]++ 

Wenn ich versuche, meine chr_counts zu drucken, ich benutze diese:

for (i in chr_count) { 
    print i,":",chr_count[i]; 
} 

Aber nicht Überraschenderweise ist die Reihenfolge von i in keiner Weise sortiert. Gibt es eine einfache Möglichkeit, über die sortierten Schlüssel von chr_count zu iterieren?

+2

Siehe http://stackoverflow.com/a/5345056/69663 - wenn Sie gawk 4 haben, sind 'PROCINFO [" sorted_in "] =" @val_num_asc "usw. sehr einfach zu benutzen. Das Handbuch zeigt viele verschiedene Optionen, wenn Sie absteigend/aufsteigend, nach Wert/Schlüssel, numerisch/zeichnerisch, Ihre eigene Funktion usw.: https://www.gnu.org/software/gawk/manual/html_node/Controlling-Scanning – unhammer

Antwort

22

Statt asort verwenden asorti(source, destination), die die Indizes in einem neuen Array sortiert und Sie werden nicht das Array zu kopieren.

Dann können Sie das Ziel-Array als Zeiger in das Quell-Array verwenden.

Für Ihr Beispiel würden Sie es wie folgt verwendet werden:

n=asorti(chr_count, sorted) 
for (i=1; i<=n; i++) { 
     print sorted[i] " : " chr_count[sorted[i]] 
} 
+0

Wow, total vergessen, obwohl man in den Dokumenten gleich dahinter gelesen hat. Dies ist definitiv die bessere Antwort. – Cascabel

+0

+1 Brilliant !!! –

+1

'asorti' funktioniert nicht mit nawk-20121220-2.fc20.x86_64. –

4

Dies ist direkt aus the documentation genommen:

populate the array data 
# copy indices 
j = 1 
for (i in data) { 
    ind[j] = i # index value becomes element value 
    j++ 
} 
n = asort(ind) # index values are now sorted 
for (i = 1; i <= n; i++) { 
    do something with ind[i]   Work with sorted indices directly 
    ... 
    do something with data[ind[i]]  Access original array via sorted indices 
} 
+0

Achtung, diese Lösung ist fehlerhaft, da dadurch Schlüssel verloren gehen, die im ursprünglichen Array dieselben Werte haben. Die akzeptierte Lösung von diesem anderen Thread hat eine Idee zur Problemumgehung: http://StackOverflow.com/a/5345056/95750 – haridsv

+1

@haridsv Nein, ich denke nicht.In dieser Frage geht es darum, nach Schlüsseln zu sortieren, nicht nach Werten, und für denselben Schlüssel können nicht zwei Werte vorhanden sein. Daher gibt es hier kein Problem. Die andere Frage, auf die Sie verweisen, ist das Sortieren nach Werten (die in der Tat nicht alle verschieden sind). Wenn Sie also versuchen würden, diesen Code dafür zu verwenden, wäre das ein Problem. Aber das ist nicht fehlerhaft, wenn Sie es für das verwenden, wofür es geschrieben ist. – Cascabel

+0

Entschuldigung .. Ich habe den Indexierungscode als "Spiegeln" Schlüssel/Werte falsch gelesen, aber nach dem erneuten Lesen, habe ich festgestellt, dass Sie eine ständig steigende Zahl als Index verwenden, nicht den ursprünglichen Wert. Danke, dass du zurückkommst und es erklärst. – haridsv

6

Beachten Sie, dass asort() und asorti() sind spezifisch für gaffen, und sind zu awk unbekannt. Für Plain Awk können Sie Ihre eigenen sort() rollen oder von woanders bekommen.

11

können Sie den Befehl sort verwenden. z.B.

for (i in data) 
print i ":", data[i] | "sort" 
0

ich auf dieses Problem vor kurzem kam und fand, dass ich mit gawk den Wert PROCINFO["sorted_in"] einstellen könnte Iterationsreihenfolge zu steuern. Ich fand eine Liste der gültigen Werte für diesen durch online procinfo Suche und landete auf die diesem GNU Awk Benutzerhandbuch Seite: https://www.gnu.org/software/gawk/manual/html_node/Controlling-Scanning.html

Hier werden Optionen des Formulars @{key|val}_{num|type|str}_{asc|desc} mit:

  • key durch Schlüssel Sortier- und val Sortierung nach Wert.
  • num Sortieren numerisch, str von Zeichenfolge und type nach zugeordneten Typ.
  • asc für aufsteigende Reihenfolge und desc für absteigende Reihenfolge.

ich einfach verwendet:

PROCINFO["sorted_in"] = "@val_num_desc" 
for (i in map) print i, map[i] 

Und die Ausgabe in absteigender Reihenfolge des Wertes wurde sortiert.