配列内の2番目に大きい値を見つける

配列内の2番目に大きい値を見つける

次のような配列があります。

array=(1 2 7 6)

2番目に大きい値を取得したい場合、出力は次のようになります。

secondGreatest=6

Bashでこれを行う方法はありますか?

答え1

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

配列の各値を1行に印刷し、並べ替え、最後の2つの値を取得し、最後の値を削除します。

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

値をsecondGreatest変数に設定します。


数字の繰り返しについてのGlenn Jackmanの指摘は素晴らしいですが、私はそれを考慮しませんでした。一意の値にのみ興味がある場合は、-uソートフラグを使用できます。

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

答え2

配列を介したbash固有のループは、最大と2番目に大きいものを追跡する必要があります。唯一のトリッキーな部分は、これらの値を初期化するときに注意することです。最大値は最初の要素で初期化され、最大値より小さい値が最初に表示されると、2番目に大きい値が初期化されます。次に、2番目に大きい値の場合は、現在の最大値より厳密に小さい場合にのみ更新します。

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

を呼び出すよりも遅いですが、sort複数の高い値(たとえば、7それ以上)に直面する7ときに厳密に小さい2番目に大きい値を選択するという利点があります。

答え3

これはDCにとって良いことです。

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

関連情報