0

As seen in another post for arrays, I tried this:

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

But it gives me the last index of the associated array.

How to get the length of my associated array?

1
  • 2
    That's a plain array with 7 elements (no sparse arrays in zsh). You need typeset -A test to set the type to associative array. Commented May 10, 2022 at 15:06

1 Answer 1

5

Unless you had run typeset -A test beforehand, that will have assigned elements of a plain array, not an associative array.

zsh arrays like the arrays of most shells and languages (the only exception that I know is ksh (and bash which copied ksh's array design)) are not sparse.

If you set elements of index 1 and 7 without setting the elements of index 2 to 6, that will still allocate an array with 7 elements, the ones from 2 to 6 being set to the empty string.

So, that code is equivalent to:

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

You can confirm it with:

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

Now, with:

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

same as

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

Recent versions also support:

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

For compatibility with ksh93 / bash.

You would define it as an associative array (keys being arbitrary sequences of bytes, not numbers, though you're free to interpret as numbers if you wish), and

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

If you wanted to count the number of elements of a plain array that are not the empty string, you could do:

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

Here relying on the fact that unquoted parameter expansions elide empty elements (to help compatibility with ksh).

Compare with:

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

(reminiscent of the Bourne shell's "$@") which doesn't elide them.

You could elide them explicitly as well with the ${array:#pattern} operator which removes elements that match a pattern:

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

Note that ${#array[@]} is the Korn shell syntax. In zsh, you can use $#array like in csh (though it also supports the Korn syntax).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .