Encuentra el segundo valor más grande en la matriz

Encuentra el segundo valor más grande en la matriz

Tengo una matriz como esta:

array=(1 2 7 6)

y le gustaría buscar el segundo valor más grande, siendo el resultado

secondGreatest=6

¿Hay alguna manera de hacer esto en bash?

Respuesta1

printf '%s\n' "${array[@]}" | sort -n | tail -2 | head -1

Imprima cada valor de la matriz en su propia línea, ordénelo, obtenga los últimos 2 valores, elimine el último valor

secondGreatest=$(printf '%s\n' "${array[@]}" | sort -n | tail -2 | head -1)

Establezca ese valor en la secondGreatestvariable.


Glenn Jackman tuvo un excelente comentario sobre los números duplicados que no consideré. Si solo te importan los valores únicos, puedes usar la -ubandera de clasificación:

secondGreatest=$(printf '%s\n' "${array[@]}" | sort -nu | tail -2 | head -1)

Respuesta2

Un bucle específico de bash a través de la matriz podría hacerlo; tienes que realizar un seguimiento del más grande y del segundo más grande. La única otra parte complicada es tener cuidado al inicializar esos valores; el valor más grande se inicializa en el primer elemento; el segundo valor más grande se inicializa la primera vez que vemos un valor que es menor que el valor más grande. Posteriormente, para el segundo valor más grande, solo lo actualizamos si es estrictamente menor que el valor más grande actual:

#!/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"

Sigue siendo más lento que llamar a sort, pero tiene el beneficio adicional de elegir el segundo valor más grande estrictamente más pequeño frente a múltiples valores altos (como 7y 7superiores).

Respuesta3

Es un buen trabajo para DC:

array=(1 2 7 6)
echo ${array[*]} | dc -f - -e '
  [lasbdsa]sB
  [dla!>Bsc1z>A]sA
  lAx
  [secondGreatest=]nlbp'

información relacionada