使用字符串在Ruby中进行意外类型转换

时间:2016-06-22 20:45:48

标签: ruby

我试图解决一个挑战,你接受一串单词但返回字符串中最长的单词。我的策略是将字符串分解为单个单词的数组并搜索数组。但是,我收到了类型转换错误。导致类型转换错误的原因是什么?这对我来说特别奇怪,因为我实际上看不到这里发生的任何类型转换。

def LongestWord(sen)

  sen1 = sen.split("/\W+/")
  grt = 0
  sen1.each do |i|
      if sen1[i].length > sen1[grt].length # Type conversion error
          grt = i
      end
  end

  sen1[grt] 
end

# keep this function call here    
puts LongestWord(STDIN.gets)  

3 个答案:

答案 0 :(得分:2)

类型转换是由数组条目i转换(可能不成功)转换为整数引起的(尽管我认为尝试将数组转换为哈希值可能是ruby,并使用i作为哈希的关键)。

您的误解是您认为您已将数组的索引传递到each的块中。传递给该块的是数组中的每个单独值。也就是说,如果您的字符串sen是'这是一个愚蠢的字符串',那么传递的值是'这','是',' ;','愚蠢'和'字符串'。

答案 1 :(得分:1)

您没有看到类型转换,但它就在那里。在不止一个地方。

正如 Derrell Durrett 在他的回答中指出的那样,你假设(错误地)将数组的索引传递给块,而不是其元素。

然后你写if sen1[i].length > sen1[grt].length。我们认为字符串'这是一个愚蠢的字符串' 。第一个元素是'这个' ,您要做的是if sen1['this'].length > sen1[0].length。由于Ruby数组总是有整数索引,因此Ruby会尝试转换'这个'到一个整数,以便在指定位置找到元素。当然这失败了!

但是你的代码并不是那么正确。一些小的改变,它将运行得非常好:

def longest_word(sen)
  sen1 = sen.split(" ")
  grt = 0
  sen1.each_index do |i|
    if sen1[i].length > sen1[grt].length 
      grt = i
    end
  end
  sen1[grt] 
end

puts LongestWord(STDIN.gets)  

现在,您正在使用sen1.each_index传递索引,并且它可以正常工作。

请注意,我将您的方法名称更改为 longest_word 。事实上,这要好得多,因为第一个大写字母保留给常量和类名。

我还想指出你没有使用好的Ruby风格。这可以这样写:

def longest_word(str)
  str.split(" ").max_by{ |s| s.length }
end

,结果会一样。

答案 2 :(得分:1)

您收到错误,因为代码运行时,isen1的第一个值,导致sen1['some string']被评估。

数组不能有字符串索引,只能有哈希值,导致类型错误。

默想:

def longest_word(sen)

  sen1 = sen.split # => ["foo", "barbaz"]
  grt = 0
  sen1.each do |i|

    i # => "foo"
    sen1 # => ["foo", "barbaz"]
    sen1[i] # => 
    sen1[grt] # => 

    sen1[i].length # => 
    sen1[grt].length # => 

    if sen1[i].length > sen1[grt].length #Type conversion error
      grt = i # => 
    end
  end


  sen1[grt] 

end

# keep this function call here    
longest_word('foo barbaz')

进一步分解,这是一个令人讨厌的问题:

sen1 = 'foo barbaz'.split
sen1['foo'] # => 

# ~> TypeError
# ~> no implicit conversion of String into Integer