Самый эффективный способ отобразить конкретную строку в хеш в Ruby - PullRequest
3 голосов
/ 17 марта 2011

Я новичок в 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 }

Единственный способ, которым я могу думать, это разделить запятую, а затем снова на точку с запятой и отобразить их.

У меня есть подозрение, что может быть какая-то магия Руби, чтобы добиться этого более эффективным и менее громоздким способом.

Любой вклад и / или хитрости / советы будут приветствоваться, так как у меня есть ощущение, что я буду подходить к таким проблемам довольно часто.

Ответы [ 4 ]

6 голосов
/ 17 марта 2011

Мы объединяем технику для преобразования набора пар ключ-значение в хеш

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) в списке аргументов, извлекает их в новые элементы и применяет к ним преобразования, чтобы адаптировать полученный хэш к спецификациям вашего примера ( в противном случае вы просто получаете хеш строк, сопоставляемых со строками).

3 голосов
/ 17 марта 2011
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 голосов
/ 17 марта 2011

Если вы используете ruby1.9, вам даже не нужно анализировать этот текст, потому что ruby1.9 принимает хеш-литералы в форме {symbol: value}, когда ключ является символом. Просто сделайте это:

eval("{#{your_string.downcase}}")
0 голосов
/ 17 марта 2011

Сначала напишите код, а затем оптимизируйте его

Если ваш код вызывает узкое место в вашей реализации 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

Последний обычно лучше работает, но, несмотря на это, это более чистый код, поэтому это не преждевременная оптимизация.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...