在Ruby中将特定字符串映射到散列的最有效方法

时间:2011-03-17 01:53:15

标签: ruby

我是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魔术以更高效,更轻松的方式实现这一目标。

任何输入和/或技巧/提示都会受到赞赏,因为我有一种感觉,我会相对经常接近这样的问题。

4 个答案:

答案 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

后者通常表现更好,但无论如何,它都是更清晰的代码,所以它不是一个不成熟的优化。