Reputation: 95267
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?
Upvotes: 5
Views: 1669
Reputation: 2981
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 )
Upvotes: 7
Reputation: 531275
Here is something completely disgusting:
% declare -A hash=([foo]=bar [baz]=zoo)
% echo ${${(kA)hash}[${${(A)hash[@]}[(i)bar]}]}
foo
Basically, it consists of two parts:
${${(A)hash[@]}[(i)bar]}
, which computes the index of bar
in an anonymous array consisting of the values of the associative array.${${(kA)hash}[...]}
, which indexes the anonymous array consisting of the keys of the associative array using the numerical index computed by the previous expansion.I'm not aware of a short equivalent to the I
flag, and I too am surprised that the seemingly obvious extension to associative arrays doesn't exist.
Upvotes: 1