Encontre o segundo maior valor na matriz

Encontre o segundo maior valor na matriz

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 secondGreatestvariá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 -usinalizador 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 7e 7acima).

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'

informação relacionada