在zsh关联数组中查找与值匹配的键?

4

在一个常规数组中,我可以使用(i)(I)来搜索匹配给定值的条目的索引(从数组的起点或终点开始的第一个匹配项):

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

这种方法不适用于关联数组,要获取一个值所在的(其中一个)键:

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

除了手动循环遍历,还有其他机制可以完成这个操作吗?


1
我假设你不想保留显式的反向映射。 - chepner
我的意思是,那也可以,而且比起要做循环来说更好。我习惯于使用bash,它甚至没有类似[(i)]的东西。但既然zsh有这个功能,我有点惊讶在关联情况下它不在那里。 - Mark Reed
我有点希望我可以使用${(vk)}而不是$((kv)},并且以相反的方式获取这些对,但没有这样的运气。 :) - Mark Reed
2个回答

6
(r)下标标志和(k)参数标志的组合应该可以给您想要的结果。
declare -A hash=([foo]=bar [baz]=zoo)
echo ${(k)hash[(r)bar]}
# => foo

(r)下标标志的手册部分只讨论了返回值,并忽略了这种用法,所以很难找到相关内容。

我之前完全没注意到下标标记的文档,因为它们在zshparam中处于关闭状态,并不在zshexpn的扩展标记旁边。我只是从例子中了解到(i)。但现在我已经找到了它们,而且我发现,实际上,(i) 被描述为 (r) 的一种变体!如果我当时看了就能立即发现它。谢谢! - Mark Reed

1
这里有一些非常恶心的东西:
% declare -A hash=([foo]=bar [baz]=zoo)
% echo ${${(kA)hash}[${${(A)hash[@]}[(i)bar]}]}
foo

基本上,它由两部分组成:
  1. ${${(A)hash[@]}[(i)bar]},它计算匿名数组中 bar 的索引,该数组由关联数组的值组成。
  2. ${${(kA)hash}[...]},它使用前面扩展计算出的数值索引来索引由关联数组的 组成的匿名数组。

我不知道是否有一个简短的等价于 I 标志的方法,我也很惊讶看到 seemingly obvious extension to associative arrays doesn't exist。


看起来zsh有足够的上下文来知道将第一个子表达式视为数组,因此您可以省略第一个A标志:${${(k)hash}[${${(A)hash}[(i)bar]}]}有效。不过还是有很多括号。谢谢! - Mark Reed

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接