【发布时间】:2011-10-20 13:48:40
【问题描述】:
我有一个这样的字符串,
str = "uu@p, xx@m, yy@n, zz@m"
我想知道如何将给定的字符串转换为哈希。 (即我的实际要求是,有多少个值(在 @ 符号之前)有 m、n 和 p。我不想要计数,我需要一个确切的值)。这样输出会更好,
{"m" => ["xx", "zz"], "n" => ["yy"], "p" => ["uu"]}
有人可以帮帮我吗?
【问题讨论】:
我有一个这样的字符串,
str = "uu@p, xx@m, yy@n, zz@m"
我想知道如何将给定的字符串转换为哈希。 (即我的实际要求是,有多少个值(在 @ 符号之前)有 m、n 和 p。我不想要计数,我需要一个确切的值)。这样输出会更好,
{"m" => ["xx", "zz"], "n" => ["yy"], "p" => ["uu"]}
有人可以帮帮我吗?
【问题讨论】:
直接复制/过去 IRB 会话:
>> str.split(/, /).inject(Hash.new{|h,k|h[k]=[]}) do |h, s|
.. v,k = s.split(/@/)
.. h[k] << v
.. h
.. end
=> {"p"=>["uu"], "m"=>["xx", "zz"], "n"=>["yy"]}
【讨论】:
Hash.new 的块形式(请参阅文档)注入一个默认值为空数组的哈希。
为新手提供更简单的代码 :)
str = "uu@p, xx@m, yy@n, zz@m"
h = {}
str.split(",").each do |x|
v,k = x.split('@')
h[k] ||= []
h[k].push(v)
end
p h
【讨论】:
FP 风格:
grouped = str.split(", ").group_by { |s| s.split("@")[1] }
Hash[grouped.map { |d, emails| [d, emails.map { |s| s.split("@")[0] }] }]
#=> {"m"=>["xx", "zz"], "n"=>["yy"], "p"=>["uu"]}
像往常一样,如果你使用Facets很酷的抽象,解决方案会更短更清晰(不需要安装整个库,只需将特定方法复制到你的扩展模块):
require 'facets'
str.split(", ").map_by { |s| s.split("@", 2).reverse }
#=> {"m"=>["xx", "zz"], "n"=>["yy"], "p"=>["uu"]}
Facets#map_by = group_by+map
【讨论】:
inject)功能对您来说还不够吗? ;-)