zsh:連想配列の長さを取得する方法は?

zsh:連想配列の長さを取得する方法は?

配列に関する他の記事でわかるように、次のことを試しました。

test[1]="hello"
test[7]="foo"
test[3]="world"
echo ${#test[@]}
7

しかし、それは私に連想配列の最後のインデックスを与えます。

連想配列の長さを取得する方法は?

答え1

これをあらかじめ実行しない限りtypeset -A test、連想配列ではなく一般配列の要素が割り当てられます。

ほとんどのシェルや言語の配列のようなzsh配列(私が知っている唯一の例外はksh(およびksh配列デザインをコピーするbash)です)は希薄ではありません。

インデックス2の要素を6に設定せずにインデックス1と7の要素を設定すると、7つの要素の配列がまだ割り当てられ、要素2〜6は空の文字列に設定されます。

したがって、このコードは次のようになります。

test=(hello '' world '' '' '' foo)

以下で確認できます。

$ typeset -p test
typeset -a test=( hello '' world '' '' '' foo )

それでは、次を使用してください。

$ typeset -A test
$ test[1]=hello test[7]=foo test[3]=world test[03]=zeroworld

それは同じです

typeset -A test=(
  1  hello
  7  foo
  3  world
  03 zeroworld
)

最新バージョンは以下もサポートしています。

typeset -A test=(
   [1]=hello
   [7]=foo
   [3]=world
  [03]=zeroworld
)

ksh93/bashとの互換性のため。

これは連想配列として定義できます(キーは数値ではなく任意のバイト列です。必要に応じて数値として解釈できます)。

$ print -r -- $#test $test[3] $test[03]
4 world zeroworld

通常の配列で空でない文字列の要素数を計算するには、次のようにします。

$ typeset -a test=()
$ test[1]=hello test[7]=foo test[3]=world
$ (){print $#} $test
3

これは、引用符なしのパラメータ拡張が空の要素を削除するという事実に依存します(kshとの互換性を助けるため)。

比較:

$ (){print $#} "$test[@]"
7

(Bourneシェルに似ています"$@")削除しません。

${array:#pattern}パターンに一致する要素を削除する演算子を使用して明示的に削除することもできます。

$ (){print $#} "${test[@]:#}"
3

これは${#array[@]}Korn シェル構文です。では、zshcshと同じように使用できます$#array(Korn構文もサポートしていますが)。

関連情報