配列で重複した値をテストする簡単な方法を見つけようとしています。重複項目がある特定の行を識別できることは良いですが、必須ではありませんが、重複項目があるかどうかを確認できることが重要です。
いくつかの数字を含む配列があります$key_array
。
# echo ${key_array[@]}
1 2 3 4 3 3
配列には複数の数字を含めることができ、その一部は他の数字と重複する可能性があります。それらは単なる整数です。 (0
たとえば、aで始まる数字は配列にまったく入ってはいけませんが、そのよう03
な場合は、異なる数字として扱うよりもキャプチャして、重複したものとして扱うことをお勧めします。)3
03
この番号が重複していることを確認する必要があります。他の方法がなければ、終了コードを使用してこれを行うことができるようです。私が望むのはこれです:
if $(some command); then
echo "Array contains duplicates."
exit 1
fi
$(commands to run after duplicate check)
最終的なアイデアは、重複がある場合、スクリプトがユーザーに通知して終了することです(重複がどこにあるかを識別することはそれほど重要ではなく、ユーザーに重複を確認するように指示するだけで十分です)。継続的に実行され、他の多くのタスクも実行されます。
どうすればこれを行うことができますか?
答え1
zsh
シェルから:
array=(1 2 3 4 3 3)
if (($#array != ${#${(u)array}})); then
print -u2 array contains duplicates
exit 1
fi
ここでは${(u)array}
配列の固有要素に拡張されるので、要素数と固有要素数を比較するだけです。
シェルにはbash
それに対応するものはありませんが、配列にはNULバイトを含めることができないため、GNUシステムを使用している場合は次のことができます。
readarray -td '' dups < <(
(( ${#array[@]} == 0 )) ||
printf '%s\0' "${array[@]}" |
LC_ALL=C sort -z |
LC_ALL=C uniq -zd
)
if ((${#dups[@]} > 0)); then
echo >&2 "array has duplicates:"
printf >&2 ' - "%s"\n' "${dups[@]}"
exit 1
fi
要素が考慮される場所コピーバイト単位で同じ場合、数値(存在する場合)が同じ場合ではありません(、、、、、、、、すべて1
が異なる01
と見なされます)。0x1
1e0
2-1
$'1\n'
' 1'
答え2
arr
整数のみが含まれ、ゼロで埋められた数字は重複と見なされる必要があると仮定すると(例:01
yes、duplicates 1
)、最初の配列の各要素を解析するときに2番目の配列を使用して「表示された」値を保持できます。arr
。
#!/bin/bash
arr=(1 2 3 4 3 3)
seen=()
for i in "${arr[@]}"; do
#Remove padding zeroes, if any
i=$((10#$i))
# If element of arr is not in seen, add it as a key to seen
if [ -z "${seen[i]}" ]; then
seen[i]=1
else
echo "Array contains a duplicate."
break
fi
done
答え3
Bash 3.Xで動作するには、次のものを使用できますuniq
。
IFS=$'\n' sort <<<"${key_array[*]}" | uniq -d; unset IFS
これにより、配列内のすべての重複要素のみが返され、返されます。
説明する
IFS=$'\n'
設定内部フィールド区切り記号新しい行文字に変換して、"${key_array[*]}"
各配列要素が新しい行に拡張されるようにします。<<<
はここにある文字列の出力をの"${key_array[*]}"
標準入力に供給しますsort
。sort
わかりました、まとめました。uniq -d
出力 "...入力で繰り返される各行の単一コピー。man uniq
"unset IFS
はいビジネスが良いをクリックしてIFS
デフォルトにリセットします。
答え4
配列に整数(正の整数)のみが含まれていると仮定すると、key_array
通常の配列は次のような事実を使用できます。足りないbash
シェルに。次のコードは、すでに処理されたキーが見つかるまで通常の配列の要素をインスタンス化するときにキー配列を繰り返します。
key_array=( '09' 1 2 3 4 3 3 '04' '001' '07' )
has_dupes () (
unset -v a
for key do
${a[10#$key]+'return'} # execute "return" if a[10#$key] is set
a[10#$key]= # set a[10#$key] to empty string
done
return 1
)
if has_dupes "${key_array[@]}"; then
echo 'array has dupes'
else
echo 'array has no dupes'
fi
has_dupes
これは整数リストを取得し、リストに重複項目がある場合は0を返し、重複項目がない場合はゼロ以外の値を返すユーティリティ関数を導入します。
標準パラメータ拡張は、${variable+word}
以前に設定された単語return
ifを挿入するために使用されます。交換するa[10#$key]
とreturn
、関数の実行が終了し、呼び出し側に終了ステータス0が返され、重複した値が見つかったことを示します。インデックスは「10#$key
基本10整数として解釈される値」を意味し、 と同じキーを同一視できます。$key
03
3