2013-08-10 6 views
0

У меня есть массив:Создание хэша Hash из массива из массива

values = [["branding", "color", "blue"], 
      ["cust_info", "customer_code", "some_customer"], 
      ["branding", "text", "custom text"]] 

У меня возникли проблемы при трансформации его хэш следующим образом:

{ 
"branding" => {"color"=>"blue", "text"=>"custom text"}, 
"cust_info" => {"customer_code"=>"some customer"} 
} 
+1

Массив # инъекционные полезно Вот. В принципе, начните с нового хеша (переданного в коллекцию) и добавляя к нему каждый элемент. См. Http://blog.jayfields.com/2008/03/ruby-inject.html для очень похожего примера. – user2246674

ответ

0

менее элегантный, но легче понять:

hash = {} 
values.each do |value| 
    if hash[value[0]] 
    hash[value[0]][value[1]] = value[2] 
    else 
    hash[value[0]] = {value[1] => value[2]} 
    end 
end 
1

Ниже приведен пример использования Enumerable#inject:

values = [["branding", "color", "blue"], 
      ["cust_info", "customer_code", "some_customer"], 
      ["branding", "text", "custom text"]] 

# r is the value we are are "injecting" and v represents each 
# value in turn from the enumerable; here we create 
# a new hash which will be the result hash (res == r) 
res = values.inject({}) do |r, v| 
    group, key, value = v  # array decomposition 
    r[group] ||= {}   # make sure group exists 
    r[group][key] = value  # set key/value in group 
    r       # return value for next iteration (same hash) 
end 

Существует несколько разных способов написать это; Я думаю, что вышеизложенное относительно просто. См. extracting from 2 dimensional array and creating a hash with array values для использования хэша (например, группы) с функцией «auto vivification».

+0

Что такое синтаксис * v? – pchu

+2

@pchu Упс, я забыл его («оператор splat») не требуется в Ruby для принудительного разложения массива в задании. Это приведет к увеличению ценности массива на RHS, но это уже массив .. исправленный код. (Хотя 'group, key, value = * v' также является законным в современном Ruby, в этом случае он не добавляет никакой пользы.) – user2246674

+0

Спасибо, что работает. В первый раз я вижу оператора splat. Не могу поверить, что Ruby имеет вызов оператора. – pchu

3

Вы можете использовать хэш-значения по умолчанию, чтобы создать что-то более разборчивыми, чем Inject:

h = Hash.new {|hsh, key| hsh[key] = {}} 
values.each {|a, b, c| h[a][b] = c} 

Очевидно, что вы должны заменить h и a, b, c переменные с точки зрения предметной области.

Бонус: Если вы нашли себя необходимости идти N уровней глубоко, проверить autovivification:

fun = Hash.new { |h,k| h[k] = Hash.new(&h.default_proc) } 
fun[:a][:b][:c][:d] = :e 
# fun == {:a=>{:b=>{:c=>{:d=>:e}}}} 

Или чрезмерно умный один вкладыш с использованием each_with_object:

silly = values.each_with_object(Hash.new {|hsh, key| hsh[key] = {}}) {|(a, b, c), h| h[a][b] = c} 
Смежные вопросы