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 keysund valuesenthalten die Schlüssel und Werte von Ain 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_valuesortiert Schlüssel lexikographisch, fügt das nFlag hinzu, um numerisch ( 9vorher 10) zu sortieren, und entfernt es, Owenn 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.*//'
))
bashes einfach zu tun. Was versuchst du zu machen?