Что правильный путь состоит в том, чтобы отсортировать связанный массив в ударе или zsh?

Если бы это работало с последним выпуском и не делает с последним, то я сказал бы, что это - ошибка. Вы могли зарегистрировать тот здесь и если они считают это восходящей проблемой в средстве отслеживания ошибки GNOME.

Около регистрации отчета об ошибках Вы могли

7
17.10.2012, 11:18
4 ответа

Zsh имеет встроенный способ отсортировать списки. Однако я не думаю, что существует способ отсортировать значения при хранении корреляции с ключами с помощью флагов расширения параметра и нижних флагов, что означает, что явный цикл необходим. Предполагая, что Ваши значения не содержат нулевой символ, можно создать массив, содержащий значения и ключи, связанные с промежуточным нулевым символом, и вид это.

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]}")

РЕДАКТИРОВАНИЕ @sch: первые 4 строки могут быть упрощены до

combined=()
for k v ("${(@kv)A}") combined+=($k$'\0'$v)

Переменные keys и values содержите ключи и значения A в произвольном, но последовательном порядке. Можно записать keys=(${(k)A}) при отсутствии пустых ключей, и так же для значений. keys_sorted_by_decreasing_value ключи видов лексикографически, добавляют n отметьте к виду численно (9 прежде 10) и удалите O если Вы хотите отсортировать в увеличивающемся порядке (в этом случае, лучшие два значения могут быть получены с нижним индексом [-2,-1]).

Ksh93 имеет способ отсортировать позиционные параметры только, с set -s; это также существует в zsh, но не в ударе 4.2. Принятие Ваших значений не содержит новые строки или управляющие символы что вид перед новыми строками:

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'}

Это все довольно сложно, таким образом, Вы могли бы также пойти для внешнего вида, который намного легче записать. Предположение, что ни ключи, ни значения не содержат управляющие символы в ksh или ударе:

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.*//'
  ))
4
27.01.2020, 20:18

Оболочка перед всем инструмент для выполнения других инструментов. Это звучит мне, Вы после языка программирования как жемчуг, рубин, Python...

Однако вот некоторое возможное решение для zsh.

В zsh можно получить отсортированный список ключей связанного массива (${(kOn)A}) или значений (${(On)A}) но не непосредственно список ключей из отсортированного списка значений (AFAIK), но Вы могли сделать вещи как:

typeset -A A B
A=(
  192.168.2.2 5
  192.168.3.2 1
  192.168.1.1 9
  192.168.8.1 9
)

for v ("${(@nO)A}") B+=("${(@kv)A[(eR)$v]}")

Таким образом, порядок (O) список значений ($A) численно (n) и for каждый vгалерея, добавляют key/vпары галереи, соответствующие значению $v (e для точного совпадения, R получить обратный список на основе значения, не ключевого) и добавить это к B ассоциативный массив.

Затем Вы вложили бы отсортированный список B:

$ printf '%s => %s\n' "${(@kv)B}"
192.168.8.1 => 9
192.168.1.1 => 9
192.168.2.2 => 5
192.168.3.2 => 1

И можно выбрать первые 2 ключа с

$ print -rl -- ${${(k)B}[1,2]}
192.168.8.1
192.168.1.1
2
27.01.2020, 20:18

"Ассоциативный массив" часто означает, что данные в массиве имеют реальное значение, которое является Вашим случаем. Внешний вид Unix идеален для этой задачи и немногих, программист C может превзойти вид Unix по характеристикам. Специально для больших данных можно адаптировать, нарезать, разветвить, принести полную мощность Unix и оболочки. Поэтому так многие окружают, и awk платформа там не беспокоятся видом.

0
27.01.2020, 20:18

Лучший способ отсортировать ассоциативный массив bash по ключу — это НЕ сортировать его.

Вместо этого получите список KEYS, отсортируйте этот список как переменную и выполните итерацию по списку. Пример :Предположим, у вас есть массив IP-адресов (ключей )и имен хостов (значений):

Альтернатива :Создайте новый список из KEYs, преобразуйте его в строки, отсортируйте его, преобразуйте обратно в список и используйте его для перебора массива.

declare -A ADDR
ADDR[192.168.1.1]="host1"
ADDR[192.168.1.2]="host2"
etc...

KEYS=`echo ${!ADDR[@]} | tr ' ' '\012' | sort | tr '\012' ' '`
for KEY in $KEYS; do
  VAL=${ADDR[$KEY]}
  echo "KEY=[$KEY] VAL=[$VAL]"
done
2
27.01.2020, 20:18

Теги

Похожие вопросы