Как реорганизовать этот код Ruby, чтобы превратить символы хеша в строки? - PullRequest
1 голос
/ 30 июля 2010

Я только что написал этот кусок кода, но я не совсем доволен этим.

data = {}
options.each{ |k,v| data.merge!({k.to_s => v}) }

В основном у меня есть:

{:a => "something", :b => "something else", :c => "blah"}

... а я хочу ...

{"a" => "something", "b" => "something else", "c" => "blah"}

... чтобы отправить его на самоцвет, который по какой-то причине не обрабатывает символы. В коде, который я написал, options - это оригинальный хеш, а data - обновленный, но если бы я мог использовать только 1 переменную, это было бы еще лучше.

Как бы вы, ребята, провели рефакторинг моего кода?

Ответы [ 5 ]

6 голосов
/ 30 июля 2010
data = Hash[options.map{ |k,v| [k.to_s,v] }]

Для достаточно большого хэша, чтобы быть интересным, между ответами нет существенной разницы

require 'benchmark'
options = Hash[('aaaa'..'zzzz').map{|i| [i.to_sym,i]}]
Benchmark.bm(100) do |x|
        x.report("map")   {Hash[options.map{ |k,v| [k.to_s,v] }] }
        x.report("zip")   {Hash[options.keys.map(&:to_s).zip(options.values)]}
        x.report("inject") {options.inject({}) { |h, (k, v)| h[k.to_s] = v; h }}
end

                          user     system      total        real
map                   3.490000   0.090000   3.580000 (  4.049015)
zip                   3.780000   0.020000   3.800000 (  3.925876)
inject                3.710000   0.110000   3.820000 (  4.289286)
3 голосов
/ 30 июля 2010

Внедрение, кажется, выигрывает:

require 'benchmark'
a = {:a => "something", :b => "something else", :c => "blah"}
Benchmark.bm(10000) do |x|
        x.report("map")   {Hash[a.map{ |k,v| [k.to_s,v] }] }
        x.report("zip")   {Hash[a.keys.map(&:to_s).zip(a.values)]}
        x.report("inject") {a.inject({}) { |h, (k, v)| h[k.to_s] = v; h }}
end

дает

user     system      total        real
map      0.000000   0.000000   0.000000 (  0.000033)
zip      0.000000   0.000000   0.000000 (  0.000018)
inject   0.000000   0.000000   0.000000 (  0.000014)
1 голос
/ 30 июля 2010

Rails добавляет метод stringify_keys в Hash.Если вы не используете Rails, вы можете просто скопировать код из ActiveSupport (с открытым исходным кодом ftw!):

def stringify_keys
  inject({}) do |options, (key, value)|
    options[key.to_s] = value
    options
  end
end
1 голос
/ 30 июля 2010

Я бы предложил что-то вроде этого:

hsh = data.inject({}) { |h, (k, v)| h[k.to_s] = v; h }

(взято из аналогичный вопрос SO )

0 голосов
/ 30 июля 2010

С помощью гема activesupport вы можете создать новый хеш (или преобразовать существующий), в котором строковые и хеш-ключи являются взаимозаменяемыми.

#!/usr/bin/ruby1.8

require 'active_support'

h = HashWithIndifferentAccess.new({'a'=>1, :b=>2})
p h[:a]     => 1
p h['a']    => 1
p h[:b]     => 2
p h['b']    => 2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...