web-dev-qa-db-ja.com

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

私はこのような配列を持っています:

array=(1 2 7 6)

2番目に大きい値を検索します。出力は

secondGreatest=6

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

2
k-a-v
printf '%s\n' "${array[@]}" | sort -n | tail -2 | head -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)
4
jesse_b

配列を介した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を呼び出すよりも低速ですが、複数の高い値(上記の77など)に直面して2番目に大きい値を厳密に選択するという追加の利点があります。

4
Jeff Schaller

それはdcにとって良い仕事です:

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