Există o soluție pentru a ocoli „nu se poate adăuga o nouă cheie în hash în timpul iterației (RuntimeError)”? (Programare, Ruby Pe Șine, Ruby, Ruby Hash)

Cristian M a intrebat.

Am o mare problemă cu așteptata RuntimeError: „can’t add a new key into hash during iteration” (nu se poate adăuga o nouă cheie în hash în timpul iterației)

În cazul meu un am un fișier YAML: test.yaml – în care am câteva chei deja adăugate.

test.yaml
key1:
key2:
key3:

Primesc conținutul fișierului într-o variabilă:

file_hash = YAML.load_file("testm.yaml")

Apoi am nevoie să fac o buclă prin acest hash și să adaug alte chei la ele:

file_hash.each do |key|
   file_hash[key] = 'key_1'
   file_hash[key] = 'key_2'
end
File.open('test.yaml', 'w') { |f| YAML.dump(file_hash, f) }

Principala problemă este că nu pot să scriu într-un hash în timp ce mă aflu într-o buclă. Nu înțeleg de ce este de așteptat acest lucru, când ai puterea de a controla blocul de buclă. există o altă modalitate prin care pot realiza ceea ce am arătat mai sus?

Notă: Folosesc RUBY 1.9.3 p547.

4 răspunsuri
catpnosis

Ruby începând cu versiunea 1.9 utilizează lazy iterație lazy, astfel că interzic adăugarea de noi chei la hash peste care iterați. Ca o soluție, puteți duplica cu ușurință hash sau să îl convertiți în array înainte de a face each.

irb(main):001:0> a={1=>1}; a.each {|k,v| a[2] = 2}
RuntimeError: can't add a new key into hash during iteration

irb(main):002:0> a={1=>1}; a.clone.each {|k,v| a[2] = 2}; a
=> {1=>1, 2=>2}

irb(main):003:0> a={1=>1}; a.to_a.each {|k,v| a[2] = 2}; a
=> {1=>1, 2=>2}

Comentarii

  • Această problemă a apărut pentru mine într-un proiect care includea o actualizare de la Ruby 1.8 la 1.9, iar această soluție a funcționat pentru mine. –  > Por Paul Fioravanti.
  • Aceasta a funcționat pentru mine. Mă întrebam de ce a funcționat scriptul meu 2.2.2 și nu a funcționat la versiunile anterioare. Mulțumesc. Pentru referință, folosiți a.to_a.each pentru a vă ușura munca –  > Por Hyra Power.
mie

Modifici hash-ul peste care iterezi. Nu poți să o faci.

În schimb, încearcă o altă abordare:

keys = [1,2,3,4]
file_hash = YAML.load_file("testm.yaml")
keys.each{ |key| file_hash[key] = 'key1' }
# => {1 => 'key1', 2 => 'key1', 3 => 'key1', 4 => 'key1'}

Comentarii

  • Mulțumesc foarte mult. Acest lucru ajută destul de mult, dar acum mă confrunt cu o altă problemă. Pentru fiecare nouă cheie inserată, trebuie să adaug valori de tip șir. Problema este că yaml creează noile chei ca șiruri de caractere. Există o modalitate de a spune yaml să nu scrie cheile ca șiruri? –  > Por Cristian M.
OfficeYA

Am avut aceeași eroare la

<%= stylesheet_link_tag 'application', 'data-turbolinks-track' => 'reload', media: 'all' %>

Așa că am rescris codul meu cu:

<% begin %>
  <%= stylesheet_link_tag 'application', 'data-turbolinks-track' => 'reload', media: 'all' %>
  <%= javascript_include_tag 'application', 'data-turbolinks-track' => 'reload' %>
<% rescue %>
  <script>
    window.location.replace "#{user_session_url()}"
  </script>
<% end %>

Nu știu care este cauza acestei probleme, dar această soluție de rezolvare funcționează pentru mine. Am testat-o cu

ab -n 100 -c 10 -w http://localhost:3000/es

Și nu am primit niciun mesaj de eroare

Игорь Хлебников

răspunsul anterior nu m-a ajutat, așa că propun ca acest ajutor să mă ajute și pe mine

a={1=>1}; a = a.clone; a[2] = 2; a