数组中的数字未键入整数?

时间:2016-12-20 17:05:48

标签: ruby types

鉴于以下内容:

def test(arr)
  cache = []
  for i in 0..arr.length
    if !cache[arr[i]] # no implicit conversion from nil to integer
      cache[arr[i]] = true
    end
    if !cache[arr[i]].to_i # no implicit conversion from nil to integer
      cache[arr[i]] = true
    end
    if !cache[arr[i].to_i] # works fine
      cache[arr[i]] = true
    end
  end
end

puts test([1, 5, 8, 11])

为什么cache[arr[i]]需要进行to_i转换?来自this answer

  

您的错误来自Ruby解释器中的C代码。用C语言实现的核心类在需要Integer时会被赋予nil。它可能有#to_i但它没有#to_int,因此结果是TypeError。

我不知道转换arr[i].to_i如何解决错误,因为arr[i]已经是整数?

3 个答案:

答案 0 :(得分:4)

您在这里遇到麻烦主要是因为您正在使用for,而且您使用不当。尽管很奇怪,for几乎没有在Ruby中使用过。相反,鼓励使用each和其他可枚举变体。

这是您的代码的Ruby惯用版本:

def test(arr)
  cache = [ ]

  arr.each_with_index do |e, i|
    cache[i] = true
  end

  cache
end

如果您正在进行索引不相关的简单转换,您甚至可以进一步重构:

def test(arr)
  arr.map do |e|
    true
  end
end

如果您在循环的每次迭代中检查了i假设的值,那么您会看到它越过数组的末尾,因此最终从外部返回nil of-bounds电话。 .to_i将此转换回0,这会解决问题,但无法解决问题。

如果您想使用0...arr.length运算符前往结尾限制<{1>}的范围,请使用...

答案 1 :(得分:2)

您的问题可能是由于迭代超过输入数组末尾的事实。

0..arr.length将为您的测试示例处理0,1,2,3,4的索引。该数组的最后一个元素的索引为3.

我相信你想要0 ... arr.length让这更有意义。

请注意第二个例子中的......和你的.. ..

答案 2 :(得分:2)

您正在访问一个不存在的元素:第一个索引为0,最后一个索引为length-1,ergo arr[arr.length]不存在并返回{{1} },这意味着nilcache[arr[arr.length]],并且由于cache[nil]是一个数组,而数组是由整数索引的,它会尝试使用{{1}将cache转换为整数但是失败了。

立即解决方法是不要迭代到nil,方法是将包含范围构建到to_int或使用排他范围。

但是真正的答案是,无论何时编写循环,你都会做错事,arr.length API中有一个方法,你宁愿使用它。不幸的是,从你的代码中可以清楚地知道它应该做什么,现在它只是返回范围并且没有副作用,所以它几乎什么都不做。

这是你在找什么?

arr.length-1