Search code examples
zshassociative-array

Find key that matches value in zsh associative array?


In a regular array, I can use (i) or (I) to search for the index of entries matching a given value (first match from the start or end of the array, respectively):

list=(foo bar baz)
echo $list[(i)bar]
# => 2

This doesn't work for associative arrays, to get (one of) the key(s) where a value is found:

declare -A hash=([foo]=bar [baz]=zoo)
echo $hash[(i)bar]
# => no output 

Is there another mechanism for doing this, other than manually looping through?


Solution

  • The (r) subscript flag combined with the (k) parameter flag should return what you want:

    declare -A hash=([foo]=bar [baz]=zoo)
    echo ${(k)hash[(r)bar]}
    # => foo
    

    The man page section on the (r) subscript flag only talks about returning values and ignores this usage, so it's hard to find.


    The (r) subscript flag will return the 'first' matching entry (associative arrays have no defined order, so 'first' can vary based on the whims of the implementation). To get all of the matches, use the (R) subscript flag:

    typeset -A hash=([foo]=false [baz]=true [bar]=false)
    typeset -a keys=( ${(k)hash[(R)false]} )
    typeset -p keys
    # => typeset -a keys=( foo bar )