将Ruby数组转换为索引哈希表?

11

我经常在Ruby中构建查找表,通常是为了缓存一些昂贵的计算或者构建一些传递给视图的东西。我想必定有一个简短,易读的习语可以实现这个功能,但我们想不到。例如,假设我想从下面开始:

[65, 66, 67, ...]
最终得到的是:

and end up with

{65 => "A", 66 => "B", 67 => "C", ...}

我们能想到的不太好看的习语包括:

array = (65..90).to_a

array.inject({}) {|hash, key| hash[key]=key.chr; hash}
{}.tap {|hash| array.each {|key| hash[key] = key.chr}}
Hash[array.zip(array.map{|key| key.chr})]

但是所有这些方式都有一点痛苦:难以阅读,容易出错,意图不明确。肯定Ruby(或某个Rails帮助程序)有一些漂亮的魔法可以做到这一点吧?

2个回答

24

关于什么呢?

 Hash[(65..90).map { |i| [i, i.chr] }]

我认为这很明显并且自我解释。此外,我认为不存在比解决这个特定任务更简单的方式,不幸的是Ruby没有类似于Python中字典推导的东西。如果你愿意,你可以使用Facets gem,其中包括了类似的功能:

require 'facets'
(65..90).mash { |i| [i, i.chr] }

1
哇。我从来没有想到一堆数组对会以那种方式解释。我本来期望它会变成 {[65, "A"] => [66, "B"], [67, "C"] => [68, "D"], ...}。这有点吓人,但我还是会使用它。谢谢! - William Pietri
3
@William: 你可以使用 Hash.[] 的两种形式:Hash[key, value, key, value, ...]Hash[[[key, value], [key, value], ... ]],内部数组表示任何可枚举的键值对。请记住,在Ruby中,有不止一种方法来做到这一点:P 另外,我添加了一个使用facets的建议。 - Niklas B.
4
如果我的associate提案被通过(参见[ruby-core:33683]),那么在这种情况下,您可以编写array.associate(&:chr)。请注意,这是英语翻译到中文的结果,已经尽力保持了原意,并且尽可能使用通俗易懂的语言。 - Marc-André Lafortune
@Marc-AndréLafortune:那真的很好。实际上,我尝试过.mash(&:chr),因为我认为这就是它的工作方式。祝你好运 :) - Niklas B.
@William:顺便提一下,我刚刚注意到你自己的例子Hash[array.zip(array.map{|key| key.chr})]实际上使用了键值对列表 :) - Niklas B.
显示剩余2条评论

1

我认为从Ruby 2.1开始,最惯用的方法是使用.to_h,因为它可以在块上调用,如下所示:

(65..90).map { |i| [i, i.chr] }.to_h

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