Ruby 错误:can't add a new key into hash during iteration (RuntimeError)

jpwangluo · May 05, 2016 · Last by LisaolRippy replied at October 13, 2025 · 2771 hits

在用 SQLAnywhere 连接 Sybase IQ,有以下程序:

def db_query( dbh, sql )
    sth = dbh.execute(sql)
    print "# of Fields:  #{sth.column_names.size}\n"
    sth.fetch do |row|
        print "\n"
        sth.column_info.each_with_index do |info, i|
            unless info["type_name"] == "LONG VARBINARY"
                print "#{info["name"]}=#{row[i]}\n" 
            end 
        end 
    end 
    sth.finish
end

程序的完整地址:http://dcx.sap.com/sa160/fr/dbprogramming/pg-ruby-dbi.html 调用改程序进行查询,出现错误:

/home/sybase/.gem/ruby/gems/dbi-0.4.5/lib/dbi/columninfo.rb:49:in `[]=': can't add a new key into hash during iteration (RuntimeError)
        from /home/sybase/.gem/ruby/gems/dbi-0.4.5/lib/dbi/columninfo.rb:49:in `block in initialize'
        from /home/sybase/.gem/ruby/gems/dbi-0.4.5/lib/dbi/columninfo.rb:42:in `each_key'
        from /home/sybase/.gem/ruby/gems/dbi-0.4.5/lib/dbi/columninfo.rb:42:in `initialize'
        from /home/sybase/.gem/ruby/gems/dbi-0.4.5/lib/dbi/handles/statement.rb:185:in `new'
        from /home/sybase/.gem/ruby/gems/dbi-0.4.5/lib/dbi/handles/statement.rb:185:in `block in column_info'
        from /home/sybase/.gem/ruby/gems/dbi-0.4.5/lib/dbi/handles/statement.rb:185:in `collect'
        from /home/sybase/.gem/ruby/gems/dbi-0.4.5/lib/dbi/handles/statement.rb:185:in `column_info'
        from Conn2IQ3.rb:29:in `db_select'
        from Conn2IQ3.rb:59:in `<main>'

这是什么原因?

终于查清楚原因了,是 dbi 包自身的问题,修改 dbi 的源代码如下: 源代码

@hash.each_key do |x|
    if x.kind_of? String
        sym = x.to_sym
        if @hash.has_key? sym
            raise ::TypeError, 
                "#{self.class.name} may construct from a hash keyed with strings or symbols, but not both" 
        end
        @hash[sym] = @hash[x]
        @hash.delete(x)
    end
end

修改为如下:

hash_size = @hash.size()
keys = @hash.keys
#puts "#{keys}"
#puts hash_size
for i in 0..hash_size-1
  keyi = keys[i]
  #puts "#{keyi}"
  if keys[i].kind_of? String
    sym = keyi.to_sym
    if @hash.has_key? sym 
      raise ::TypeError, "#{self.class.name} may construct from a hash keyed with strings or symbols, but not both" 
    end 
    @hash[sym] = @hash[keyi]
    @hash.delete(keyi)
  end 
end 
a = {a: 1, b: 2}
a.each { |k, v| a[v] = a[k] } # will raise "can't add a new key into hash during iteration"
a.dup.each { |k, v| a[v] = a[k] } # works

#2 楼 @angelfan 照这种方法也可以解决

This error needs to be fixed immediately so that queries can continue to run smoothly. It is challenging to encounter such problem while working with iq test free!

Interesting error! This usually happens when you try to modify a hash while looping through it. One workaround is to collect the keys to be added in a separate array, then add them after the iteration is complete. I've seen similar issues tackled using techniques shared on sites dedicated to puzzle solving, even relating to games like Wordle Unlimited. Good luck debugging!

You need to Sign in before reply, if you don't have an account, please Sign up first.