zsh:如何获取关联数组长度?

zsh:如何获取关联数组长度?

正如在另一篇关于数组的文章中看到的,我尝试了以下方法:

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

但它给了我关联数组的最后一个索引。

如何获取关联数组的长度?

答案1

除非您事先运行过typeset -A test,否则将分配普通数组的元素,而不是关联数组。

zsh 数组与大多数 shell 和语言的数组一样(我知道的唯一例外是 ksh(以及复制 ksh 数组设计的 bash))并不稀疏。

如果设置索引 1 和 7 的元素,而不将索引 2 的元素设置为 6,则仍然会分配一个包含 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 shell 的"$@"),它不会删除它们。

您也可以使用删除与${array:#pattern}模式匹配的元素的运算符显式删除它们:

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

请注意,这${#array[@]}是 Korn shell 语法。在 中zsh,您可以像 csh 中一样使用$#array(尽管它也支持 Korn 语法)。

相关内容