【问题标题】:Ruby implicit conversion of String into Integer (typeError)Ruby 将 String 隐式转换为 Integer (typeError)
【发布时间】:2018-08-31 16:16:51
【问题描述】:

我正在尝试使用 YAML 文件,从中读取并向其写入值列表。在第一次运行此脚本时,正确创建了 yaml 文件,但在第二次运行时,它会引发我不知道要修复的转换类型错误。

db_yml = 'store.yml'

require 'psych'
begin
    if File.exist?(db_yml)
        yml = Psych.load_file(db_yml)
        puts "done load"        

        yml['reminders']['reminder_a'] = [123,456] 
        yml['reminders']['reminder_b'] = [457,635,123]
        File.write(db_yml, Psych.dump(yml) ) 
    else 
      #the file does not exist yet, create an empty one.
        File.write(db_yml, Psych.dump(
        {'reminders' => [
            {'reminder_a'=> [nil]}, 
            {'reminder_b'=> [nil]}
        ]}
  )) #Store
    end
rescue IOError => msg  
  # display the system generated error message  
  puts msg 
end

在第一次运行时生成文件 store.yml:

---
reminders:
- reminder_a:
  - 
- reminder_b:
  - 

到目前为止一切顺利。但是在第二次运行时它失败了

done load
yamlstore.rb:23:in `[]=': no implicit conversion of String into Integer (TypeError)
        from yamlstore.rb:23:in `<main>'

你能告诉我哪里出错了吗?

【问题讨论】:

    标签: ruby yaml


    【解决方案1】:

    错误消息表明您传递了String,其中Ruby 期望可以隐式转换为Integer 的内容。 Ruby 期望可以隐式转换为Integer 的第一个地方是索引到Array 时。因此,每当您看到此错误消息时,您可以 99% 确定您正在使用您认为是 Integer 但不是的东西来索引 Array,或者您正在索引您认为的 Array是别的东西(很可能是Hash)。 (另一种可能性是您正在尝试使用IntegersStrings 的组合来进行算术运算。)

    仅仅因为 Ruby 是一种动态类型的编程语言,并不意味着您不需要关心类型。特别是,YAML 是一种(某种程度上)类型化的序列化格式。

    您正在创建的文件类型如下所示:

    Map<String, Sequence<Map<String, Sequence<Int | null>>>>
    

    但是,您正在访问它,就好像它是这样输入的:

    Map<String, Map<String, Sequence<Int | null>>>
    

    更具体地说,您正在创建与键 'reminders' 对应的值作为 maps (Hashes)。 Arrays 被 Integers 索引。

    但是,您使用String 对其进行索引,就好像它是Hash

    因此,您需要更改访问值的方式,如下所示:

    yml['reminders'][0]['reminder_a'] = [123, 456]
    #               ↑↑↑
    
    yml['reminders'][1]['reminder_b'] = [457,635,123]
    #               ↑↑↑
    

    或者像这样改变你初始化文件的方式:

    File.write(db_yml, Psych.dump(
    { 'reminders' => {
    #                ↑
        'reminder_a' => [nil],
    #  ↑                     ↑
        'reminder_b' => [nil]
    #  ↑                     ↑
    }
    

    因此生成的 YAML 文档如下所示:

    ---
    reminders:
      reminder_a:
        - 
      reminder_b:
        - 
    

    【讨论】:

    • 两个答案都是一样的,这个布局很好,但为了简洁起见,我选择了另一个。尽管如此,还是非常感谢您详细解释,非常感谢! +1
    【解决方案2】:

    YAML 文件没有问题。但是,您使用以下结构创建文件:

    yaml = {
      'reminders' => [
        {'reminder_a'=> [nil]}, 
        {'reminder_b'=> [nil]}
      ]
    }
    

    注意yaml['reminders'] 的内容是一个数组。哪里出错了:

    reminders = yaml['reminders']
    reminder_a = reminders['reminder_a'] # <= error
    
    # in the question example:
    # yml['reminders']['reminder_a'] = [123,456]
    

    由于reminders 是一个数组,因此您无法通过将字符串作为索引传递来访问它。您有 2 个选择:

    1. 在我看来,最好的选择(如果您想按键访问提醒)是更改结构以使用散列而不是数组:

      yaml = {
        'reminders' => {
          'reminder_a'=> [nil], 
          'reminder_b'=> [nil]
        }
      }
      

      通过上述结构,您可以通过以下方式访问您的提醒:

      yaml['reminders']['reminder_a']
      
    2. 有点笨拙,找到正确key的数组元素:

      yaml['reminders'].each do |reminder|
        reminder['reminder_a'] = [123,456] if reminder.key? 'reminder_a'
        reminder['reminder_b'] = [457,635,123] if reminder.key? 'reminder_b'
      end
      

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多