O Zsh tem uma maneira interna de ordenar listas. No entanto, não acho que haja uma maneira de classificar os valores, mantendo a correlação com as chaves usando sinalizadores de expansão de parâmetro e sinalizadores de subscrito , o que significa que um sinal explícito loop é necessário. Supondo que seus valores não contenham um caractere nulo, você pode construir uma matriz contendo os valores e chaves concatenados com um caractere nulo no meio e ordenar isso.
keys=("${(@k)A}")
values=("${(@v)A}")
combined=()
for ((i=1; i <= $#values; i++)) { combined[i]=($values[i]$'combined=()
for k v ("${(@kv)A}") combined+=($k$'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'}
'$v)
'$keys[i]); }
keys_sorted_by_decreasing_value=("${${(@On)combined}#*$'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.*//'
))
'}")
keys_of_the_top_two_values=("${(@)keys_sorted_by_decreasing_value[1,2]}")
EDIT by @sch: as primeiras 4 linhas podem ser simplificadas para
keys=("${(@k)A}")
values=("${(@v)A}")
combined=()
for ((i=1; i <= $#values; i++)) { combined[i]=($values[i]$'combined=()
for k v ("${(@kv)A}") combined+=($k$'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'}
'$v)
'$keys[i]); }
keys_sorted_by_decreasing_value=("${${(@On)combined}#*$'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.*//'
))
'}")
keys_of_the_top_two_values=("${(@)keys_sorted_by_decreasing_value[1,2]}")
As variáveis keys
e values
contêm as chaves e valores de A
em uma ordem arbitrária, mas consistente. Você pode escrever keys=(${(k)A})
se não houver chaves vazias e, da mesma forma, para valores. keys_sorted_by_decreasing_value
classifica as chaves lexicograficamente, adiciona o n
para ordenar numericamente ( 9
antes de 10
) e remove O
se você quiser ordenar em ordem crescente (caso em que os dois primeiros valores podem ser obtidos com o subscrito [-2,-1]
).
O Ksh93 tem uma maneira de classificar apenas os parâmetros posicionais, com set -s
; isto também existe em zsh mas não em bash 4.2. Presumindo que seus valores não contêm novas linhas ou caracteres de controle que classificam antes de novas linhas:
Isso tudo é muito complexo, então você também pode optar pelo tipo externo, que é muito mais fácil de escrever. Assumindo que nem chaves nem valores contenham caracteres de controle, em ksh ou bash:
%pre%