2016-02-28 2 views
0

Я пытаюсь преобразовать массив в хэш, итерации через него. У меня есть следующий массив:Преобразование Ruby Array в хэш путем петли через

weekdays = [["Monday",2],["Tuesday",4],["Thursday",5]] 

Я зацикливание через массив для создания хэша, как так:

hash_weekdays = Hash.new 
weekdays.each do |item| 
    hash_weekdays["weekday"] = item[0] 
    hash_weekdays["number"] = item[1] 
end 

Это, однако, только показывает мне последний день недели. Любые идеи о том, куда идти отсюда? Благодаря!

ответ

1

Хэш содержит пары ключ-значение. Каждый ключ ссылается только на одно значение, и каждый ключ является uniq в хеше. Значения ваших ключей weekday и number будут перезаписаны каждой итерацией. Вот почему вы получаете результат только последней итерации.

Вы можете преобразовать его в массив хэшей в качестве альтернативы.

weekdays.map{|day, number| {weekday:day, number: number}} 
# => [{:weekday=>"Monday", :number=>2}, {:weekday=>"Tuesday", :number=>4}, {:weekday=>"Thursday", :number=>5}] 

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

weekdays.to_h 
# => {"Monday"=>2, "Tuesday"=>4, "Thursday"=>5} 

или

weekdays.to_h.invert 
# => {2=>"Monday", 4=>"Tuesday", 5=>"Thursday"} 
+0

спасибо за объяснение @guitarman, есть ли Aw ay, чтобы пересмотреть мой 'weekdays.each' цикл, чтобы преодолеть это? – Brandon

+0

спасибо! отлично работает :) – Brandon

1

Вы могли бы сделать это вместо:

weekdays.to_h #=> {"Monday"=>2, "Tuesday"=>4, "Thursday"=>5} 

или фиксируя код:

weekdays = [["Monday",2],["Tuesday",4],["Thursday",5]] 

hash_weekdays = Hash.new 
weekdays.each do |item| 
    hash_weekdays[item[0]] = item[1] 
end 

p hash_weekdays #=> {"Monday"=>2, "Tuesday"=>4, "Thursday"=>5} 
1

Вам нужно изменить свой код на следующее:

hash_weekdays = Hash.new 
weekdays.each do |item| 
    hash_weekdays[item[0]] = item[1] 
end 
hash_weekdays 
#=> {"Monday"=>2, "Tuesday"=>4, "Thursday"=>5} 

Когда первый элемент weekdays (["Monday",2]) передается в блок, переменная блока присваивается его значение:

item = ["Monday",2] 

Поскольку вы должны ссылаться на каждый элемент item, это обычно используют два блока переменных, значения которых заданы с помощью параллельного назначения (ака множественное присваивание):

day, nbr = ["Monday",2] 
    #=> ["Monday", 2] 
day #=> "Monday" 
nbr #=> 2 

Это позволяет писать

hash_weekdays = {} # the more common way of writing hash_weekdays = Hash.new 
weekdays.each { |day, nbr| hash_weekdays[day] = nbr } # used {...} rather than do..end 
hash_weekdays 

, который, возможно, яснее.

Обратите внимание, что вы сначала инициализируете hash_weekdays пустым хешем, затем в конце вам нужна строка hash_weekdays, если вы хотите получить новое значение хэша (например, в качестве последней строки метода). Вы можете уменьшить это к одной линии (очень рубин, как), используя метод Enumerable#each_with_object:

weekdays.each_with_object({}) { |item, hash_weekdays| hash_weekdays[item[0]] = item[1] } 
    #=> {"Monday"=>2, "Tuesday"=>4, "Thursday"=>5} 

Заметим, что это использует параллельное назначение.Первый элемент передается в блок, [["Monday", 2], {}], назначается следующим образом:

item, hash_weekdays = weekdays.each_with_object({}).next 
    #=> [["Monday", 2], {}] 
item 
    #=> ["Monday", 2] 
hash_weekdays 
    #=> {} 

путь Рубин использовать параллельное назначение в несколько более сложным образом:

weekdays.each_with_object({}) { |(day, nbr), hash_weekdays| 
    hash_weekdays[day] = nbr } 
    #=> {"Monday"=>2, "Tuesday"=>4, "Thursday"=>5} 

Как уже отмечалось, то наиболее простой ответ заключается в использовании метода Hash::[] или (введен в v2.0) Array#to_h:

Hash[weekdays] 
    #=> {"Monday"=>2, "Tuesday"=>4, "Thursday"=>5} 

Hash[*weekdays.flatten] #=> Hash["Monday", 2, "Tuesday", 4, "Thursday", 5] 
    #=> {"Monday"=>2, "Tuesday"=>4, "Thursday"=>5} 

weekdays.to_h 
    #=> {"Monday"=>2, "Tuesday"=>4, "Thursday"=>5} 
Смежные вопросы