2013-11-21 2 views
-1

Я хотел бы превратить этотЧто такое элегантный способ модификации хэш внутри массива в пределах вложенного хэша в Ruby,

def some_process(k,v) 
    return "#{v}_#{k}" 
end 

a_hash = { 
    "i_love_hashes" => { 
     "thing" => 20, 
     "other_thing" => "0", 
     "yet_another_thing" => "i disagree", 
     "_peculiar_thing" => [ 
      {"count" => 30, 
      "name" => "freddie"}, 
      {"count" => 15, 
      "name" => "johhno"}, 
      {"count" => 12, 
      "name" => "mohammed"}, 
     ] 
    }, 
    "as_do_i" => { 
     "thing" => 10, 
     "other_thing" => "2", 
     "yet_another_thing" => "i strongly agree", 
     "_peculiar_thing" => [ 
      {"count" => 10, 
      "name" => "frodo"}, 
      {"count" => 4, 
      "name" => "bilbo"}, 
      {"count" => 2, 
      "name" => "elizabeth"}, 
     ] 
    } 
} 

в этом

{ 
"i_love_hashes"=>{ 
    "thing"=>20, 
    "other_thing"=>"0", 
    "yet_another_thing"=>"i disagree", 
    "_peculiar_thing"=> [ 
     {"count"=>30, "name"=>"freddie", :sinister_name=>"freddie_i_love_hashes"}, 
     {"count"=>15, "name"=>"johhno", :sinister_name=>"johhno_i_love_hashes"}, 
     {"count"=>12, "name"=>"mohammed", :sinister_name=>"mohammed_i_love_hashes"} 
     ]}, 
"as_do_i"=>{ 
    "thing"=>10, 
    "other_thing"=>"2", 
    "yet_another_thing"=>"i strongly agree", 
    "_peculiar_thing"=>[ 
     {"count"=>10, "name"=>"frodo", :sinister_name=>"frodo_as_do_i"}, 
     {"count"=>4, "name"=>"bilbo", :sinister_name=>"bilbo_as_do_i"}, 
     {"count"=>2, "name"=>"elizabeth", :sinister_name=>"elizabeth_as_do_i"} 
     ] 
    } 
} 

это код, я в настоящее время с помощью для достижения этого

a_hash.each_with_object({}) do |(k,v),o| 
    o.merge!({k => 
     v.each_with_object({}) do |(a,b),g| 
     g.merge!({ a => 
      (b.is_a?(Array) ? b.collect {|x| x.merge({sinister_name: (some_process k, x["name"])})} : b) 
      }) 
     end 
    }) 
end 

Игнорирование конкретных деталей того, что возвращается «some_process» (что важно, что это зависит от внешнего ключа и внутренних значений имени в этом примере), есть ли альтернативы, которые считаются более элегантными?

+0

Почему '.each_with_object()' и не 'inject()'? – Phlip

+1

@Phlip Я бы почти всегда использовал для этого инъекцию, но второй ответ [здесь] (http://stackoverflow.com/questions/5481009/why-is-enumerableeach-with-object-deprecated) дает вескую причину, почему каждый_with_object действительный. –

+0

@Phlip: какова будет эквивалентная версия на основе инъекций? –

ответ

0

Почему бы не сделать рекурсивную функцию?

def add_siniter(hash) 
    hash[:siniter_name] = "#{hash['name']}_i_love_hashes" 
    hash 
end 

def format_hash(item) 
    case item 
    when Hash then item.keys.each{|key| format_hash(item[key])} 
    when Array then item.map!{|h| add_siniter(h)} 
    end 
end 

format_hash(a_hash) 
+0

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

+0

Кроме того, метод format_hash, который вы указали, только возвращает массив из двух ключей верхнего уровня при запуске с предоставленным хешем. –

Смежные вопросы