Динамические хэши: добавление большего к хэшу внутри хэша

#ruby #hash

#ruby #хэш

Вопрос:

Новичок в Ruby. Добавил хэш в хэш, но не смог «добавить» больше ключей и значений к хэшу, не записав первый ключ и значение в новый хэш. Пример кода:

 contacts = {
    "Jason" => {
      "phone" => 833,
      "twitter" => "sliceyboi",
      "email" => "crystal@lake"
    },
    "Freddy" => {
      "phone" => 666,
      "tiktok" => "asdf",
      "instagram" => "def",
      "email" => "in.your@dreams"
    }
  }

while true
puts contacts

new_key_and_value = {}

puts "add name"

name_key = gets.chomp

puts "add media:"
new_key = gets.chomp
 
puts "add #{new_key} info:"
new_value = gets.chomp

new_key_and_value[new_key] = new_value

contacts[name_key] = new_key_and_value
end
  

Я могу добавить «Чаки» «электронная почта: кукла @ игрушки». Но если я пройдусь еще раз, для любого из имен для Чаки или любого из них, я надеялся добавить больше медиафайлов, а не перезаписать. Я знаю, что это как-то связано с созданным новым хэшем.

Так, например, что он делает:

 add name

>Chucky
add media:
>email
add email info:
> doll@toys

{"Jason"=> 
     { "phone"=>833, 
     "twitter"=>"sliceyboi", 
     "email"=>"crystal@lake"},
 
"Freddy"=>
      {"phone" => 666,
      "tiktok" => "asdf",
      "instagram" => "def",
      "email" => "in.your@dreams"}, 

"Chucky"=>
     {"email"=>"doll@toys"}
    }

add name
>Chucky
add media:
>tiktok
add tiktok info:
>chplay

{"Jason"=> 
     { "phone"=>833, 
     "twitter"=>"sliceyboi", 
     "email"=>"crystal@lake"},
 
"Freddy"=>
      {"phone" => 666,
      "tiktok" => "asdf",
      "instagram" => "def",
      "email" => "in.your@dreams"}, 

"Chucky"=>
     {"tiktok"=>"chplay"}
    }

  

ищете:

 {"Jason"=> 
     { "phone"=>833, 
     "twitter"=>"sliceyboi", 
     "email"=>"crystal@lake"},
 
"Freddy"=>
      {"phone" => 666,
      "tiktok" => "asdf",
      "instagram" => "def",
      "email" => "in.your@dreams"}, 

"Chucky"=>
     {"email"=>"doll@toys",
     "tiktok"=>"chplay",
}
    }

  

Так что это добавление в конец хэша Чаки

Комментарии:

1. Я предлагаю, чтобы всякий раз, когда вы приводите пример, вы показывали ожидаемый результат (как объект Ruby). Это, как правило, полезно для читателей.

Ответ №1:

Я знаю, что это как-то связано с созданным новым хэшем.

Вы правы. Все, что вам нужно сделать, это удалить new_key_and_value = {} и вместо того, где вы пишете

 new_key_and_value[new_key] = new_value

contacts[name_key] = new_key_and_value
  

напишите

 # if contact doesn't exist create it.
if not contacts.key?(name_key) then contacts[name_key] = {} end

contacts[name_key][new_key] = new_value
  

В качестве альтернативы вы могли бы заменить new_key_and_value = {} на new_key_and_value = contacts.key?(name_key) ? contacts[name_key] : {} , но если этот контакт большой, вы создаете копию в памяти без причины, и это менее наглядно.

Ответ №2:

Вы могли бы использовать следующие методы.

 def add_contact(contacts)
  name = seek("What is name to add?")
  h = {}
  loop do
    key, val = add_media
    break if key == ''
    h[key] = val
  end
  contacts[name] = h
  contacts 
end

def add_media
  key = seek("Add media (enter empty string when finished")
  return key if key.empty?
  [key, seek("Add #{key} information")]
end

def seek(msg)
  print "#{msg}: "
  gets.chomp
end
  

Если диалог был:

 add_contact contacts
What is name to add?: Chucky
Add media (enter empty string when finished: email
Add email information: doll@toys
Add media (enter empty string when finished: tiktok
Add tiktok information: chplay
Add media (enter empty string when finished: 
  

метод вернет:

 #=> { "Jason"=>{
#       "phone"=>833,
#       "twitter"=>"sliceyboi",
#       "email"=>"crystal@lake"
#     },
#     "Freddy"=>{
#       "phone"=>666,
#       "tiktok"=>"asdf",
#       "instagram"=>"def",
#       "email"=>"in.your@dreams"
#     },
#     "Chucky"=>{
#       "email"=>"doll@toys",
#       "tiktok"=>"chplay"
#     }
#   } 
  

Последняя строка add_contact является необязательной. contacts будет изменен по желанию, если он отсутствует. Я включил его, чтобы можно было написать что-то вроде

 add_contact(contacts).each { |k,v| .... }
  

вместо

 add_contact(contacts)
contacts.each { |k,v| .... }
  

если это необходимо.