web-dev-qa-db-ja.com

'反復中にハッシュに新しいキーを追加できない(RuntimeError)'をバイパスする解決策はありますか?

予想されるRuntimeErrorに大きな問題があります:「反復中にハッシュに新しいキーを追加できません」

私の場合、YAMLファイルtest.yamlがあります。このファイルにはすでにいくつかのキーが追加されています。

test.yaml
key1:
key2:
key3:

ファイルの内容を変数で取得しています:

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

次に、このハッシュをループして、他のキーを追加する必要があります。

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) }

主な問題は、ループ中にハッシュに書き込めないことです。ループブロックを制御する力があるのに、なぜこれが予想されるのかわかりません。上に示したことを達成する別の方法はありますか?

注:私はRuby 1.9.3p547を使用しています

16
Cristian M

1.9以降のRubyはlazy反復を使用しているため、反復するhashに新しいキーを追加することを禁じています。解決策として、eachを実行する前に、hashを簡単に複製するか、arrayに変換することができます。

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}
17
catpnosis

繰り返し処理しているハッシュを変更しています。あなたはそれをすることはできません。

代わりに、別のアプローチを試してください。

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'}
10
mie

私はで同じエラーがありました

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

だから私は自分のコードを次のように書き直します:

<% 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 %>

この問題の原因はわかりませんが、この回避策は有効です。私はそれをテストしました

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

そして、私はエラーメッセージを受け取りませんでした

2
OfficeYA

前の答えは私を助けなかったので、私は私のためにそれを提案します

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