
Eu tenho uma matriz assim:
array=(1 2 7 6)
e gostaria de procurar o segundo maior valor, com a saída sendo
secondGreatest=6
Existe alguma maneira de fazer isso no bash?
Responder1
printf '%s\n' "${array[@]}" | sort -n | tail -2 | head -1
Imprima cada valor do array em sua própria linha, classifique-o, obtenha os 2 últimos valores, remova o último valor
secondGreatest=$(printf '%s\n' "${array[@]}" | sort -n | tail -2 | head -1)
Defina esse valor para a secondGreatest
variável.
Glenn Jackman tinha um excelente argumento sobre números duplicados que não considerei. Se você se preocupa apenas com valores únicos, você pode usar o -u
sinalizador de classificação:
secondGreatest=$(printf '%s\n' "${array[@]}" | sort -nu | tail -2 | head -1)
Responder2
Um loop específico do bash através do array poderia fazer isso; você deve acompanhar o maior e o segundo maior. A única outra parte complicada é ter cuidado ao inicializar esses valores; o maior valor é inicializado no primeiro elemento; o segundo maior valor é inicializado na primeira vez que vemos um valor menor que o maior valor. Posteriormente, para o segundo maior valor, só o atualizamos se for estritamente menor que o maior valor atual:
#!/bin/bash
array=(7 7 6 2 1)
if [ "${#array[@]}" -lt 2 ]
then
echo Incoming array is not large enough >&2
exit 1
fi
largest=${array[0]}
secondGreatest='unset'
for((i=1; i < ${#array[@]}; i++))
do
if [[ ${array[i]} > $largest ]]
then
secondGreatest=$largest
largest=${array[i]}
elif (( ${array[i]} != $largest )) && { [[ "$secondGreatest" = "unset" ]] || [[ ${array[i]} > $secondGreatest ]]; }
then
secondGreatest=${array[i]}
fi
done
echo "secondGreatest = $secondGreatest"
Ainda é mais lento do que chamar to sort
, mas tem o benefício adicional de escolher o segundo maior valor estritamente menor em face de vários valores altos (como 7
e 7
acima).
Responder3
É um bom trabalho para dc :
array=(1 2 7 6)
echo ${array[*]} | dc -f - -e '
[lasbdsa]sB
[dla!>Bsc1z>A]sA
lAx
[secondGreatest=]nlbp'