Zsh verfügt über eine integrierte Methode zum Sortieren von Listen. Ich glaube jedoch nicht, dass es eine Möglichkeit gibt, die Werte zu sortieren, während die Korrelation mit den Schlüsseln mithilfe von Parametererweiterungs- und Indexflags beibehalten wird , was bedeutet, dass eine explizite Schleife erforderlich ist. Angenommen, Ihre Werte enthalten kein Nullzeichen, können Sie ein Array erstellen, das die Werte und Schlüssel enthält, die mit einem Nullzeichen dazwischen verknüpft sind, und dieses sortieren.
keys=("${(@k)A}")
values=("${(@v)A}")
combined=()
for ((i=1; i <= $#values; i++)) { combined[i]=($values[i]$'\0'$keys[i]); }
keys_sorted_by_decreasing_value=("${${(@On)combined}#*$'\0'}")
keys_of_the_top_two_values=("${(@)keys_sorted_by_decreasing_value[1,2]}")
EDIT by @sch: Die ersten 4 Zeilen können vereinfacht werden
combined=()
for k v ("${(@kv)A}") combined+=($k$'\0'$v)
Die Variablen keys
und values
enthalten die Schlüssel und Werte von A
in einer beliebigen, aber konsistenten Reihenfolge. Sie können schreiben, keys=(${(k)A})
wenn keine leeren Schlüssel vorhanden sind, und dies gilt auch für Werte. keys_sorted_by_decreasing_value
sortiert Schlüssel lexikographisch, fügt das n
Flag hinzu, um numerisch ( 9
vorher 10
) zu sortieren, und entfernt es, O
wenn Sie in aufsteigender Reihenfolge sortieren möchten (in diesem Fall können die beiden obersten Werte mit dem Index erhalten werden [-2,-1]
).
Ksh93 bietet die Möglichkeit, nur die Positionsparameter mit zu sortieren set -s
. Dies existiert auch in zsh, aber nicht in bash 4.2. Angenommen, Ihre Werte enthalten keine Zeilenumbrüche oder Steuerzeichen, die vor Zeilenumbrüchen sortiert werden:
keys=("${!A[@]}")
combined=()
for ((i=0; i <= ${#keys}; i++)); do combined[i]=(${A[${keys[$i]}]}$'\n'${keys[$i]}); done
set -A sorted -s "${combined[@]}"
top_combined=${sorted[${#sorted[@]}-1]} # -2 for the next-to-largest, etc.
top_key=${top_combined#*$'\n'}
Das ist alles ziemlich komplex, also können Sie sich auch für die externe Sortierung entscheiden, die viel einfacher zu schreiben ist. Angenommen, weder Schlüssel noch Werte enthalten Steuerzeichen in ksh oder bash:
IFS=$'\n'; set -f
keys_sorted_by_decreasing_value=($(
for k in "${!A[@]}"; do printf '%s\t%s\n' "${A[$k]}" "$k"; done |
sort | sed $'s/\t.*//'
))
bash
es einfach zu tun. Was versuchst du zu machen?