我是Ruby的新手,正在开发一个解析我的一些报告的CLI应用程序。我想通过这一行找出实现以下目标的最有效方法:
MAXCONN: 2000, MAXSSL_CONN: 500, PLAINCONN: 34, AVAILCONN: 1966, IDLECONN: 28, SSLCONN: 0, AVAILSSL: 500
我想将此映射到哈希值:
{ :maxconn => 2000, :maxssl_conn => 500, :plainconn => 34, :availconn => 1966, :idleconn => 28, :sslconn => 0, :availssl => 500 }
我能想到的唯一方法就是用逗号分割,然后再用分号分开并映射它们。
我有一种潜在的怀疑,可能会有一些Ruby魔术以更高效,更轻松的方式实现这一目标。
任何输入和/或技巧/提示都会受到赞赏,因为我有一种感觉,我会相对经常接近这样的问题。
答案 0 :(得分:6)
我们将用于转换一堆键值对的技术组合成一个哈希
Hash[[[k1, v1], [k2, v2], ...]] #=> { k1 => v1, k2 => v2, ... }
使用正则表达式方法String#scan
,它通过一个字符串并收集数组中的匹配项,以获取
Hash[reports.scan(/(\w+): (\w+)/).map { |(first, second)| [first.downcase.to_sym, second.to_i] }]
这也使用带有Enumerable#map
的块,它将数组解释为参数列表中的(first, second)
元素对,将这些元素提取到新元素中,并将转换应用于它们,以便将生成的哈希定制为你的例子的规范(否则,你只是得到一个字符串的哈希映射到字符串)。
答案 1 :(得分:3)
hash = {}
input.scan /(\w)+\:(\d+)\,/ do |key, val|
hash[key.downcase.to_sym] = val.to_i
end
似乎最明显。
你可以(有一些警告)这样做:
hash = Hash[*eval(string).map{|k,v| [k.downcase.to_sym, v]}.flatten]
但这真的迫使不应该出现的单行。
当然分裂它并不是一个可怕的想法:
hash = input.split(",").each_with_object({}) do |str, h|
k,v = str.split(":")
h[k.downcase.to_sym] = v.to_i
end
答案 2 :(得分:2)
如果您使用的是ruby1.9,则甚至不需要解析该文本,因为当密钥是符号时,ruby1.9接受{symbol: value}
形式的散列文字。简单地说,这样做:
eval("{#{your_string.downcase}}")
答案 3 :(得分:0)
如果你的代码导致你的Ruby实现出现瓶颈,那么你要做的第一件事就是找出它是字符串拆分,还是哈希创建,或者将新哈希添加到它所在的任何数组中(这个是我最担心的一步!),这导致了瓶颈。
关于将新哈希添加到它所在的数组中,通常你不应该这样做
array_of_hashes = []
lines.each do |line|
hash = create_hash(line)
array_of_hashes << hash
end
相反,做
array_of_hashes = lines.map do |line|
hash = create_hash(line)
hash
end
后者通常表现更好,但无论如何,它都是更清晰的代码,所以它不是一个不成熟的优化。