【问题标题】:Trouble when using match on an array在数组上使用匹配时出现问题
【发布时间】:2013-11-06 22:11:08
【问题描述】:

我想做的是创建一个可以将数组作为参数的方法。数组中应该有一些数字。该方法将返回数组包含其中每个数字的次数。我知道可能有很多方法可以做到这一点,但如果人们能帮助我理解为什么我的方法行不通,而不是仅仅建议我做一些完全不同的事情,我将不胜感激。

所以我先试试这个方法

def score (dice)
    dice.each do |die|
        x = /(die)/.match(dice.to_s).length
    end
    x
end

并用score ([5])expecting 调用它以获得1的输出。但是,我得到了

NoMethodError: undefined method `length' for nil:NilClass
    from t2.rb:22:in `block in score'
    from t2.rb:21:in `each'
    from t2.rb:21:in `score'
    from (irb):2
    from /home/macs/.rvm/rubies/ruby-2.0.0-p247/bin/irb:13:in `<main>'

我也尝试稍微改变匹配语句(去掉to_s)所以它是

 def score (dice)
        dice.each do |die|
            x = /(die)/.match(dice).length
        end
        x
    end

并用score ([5]) 调用它,我明白了

TypeError: no implicit conversion of Array into String
    from t2.rb:22:in `match'
    from t2.rb:22:in `block in score'
    from t2.rb:21:in `each'
    from t2.rb:21:in `score'
    from (irb):2
    from /home/macs/.rvm/rubies/ruby-2.0.0-p247/bin/irb:13:in `<main>'

真的不知道我应该如何完成这种匹配。

【问题讨论】:

  • 我不确定你要去哪里。这是什么/die/ 模式,它与整数数组有什么关系?
  • @SergioTulentsev 当我调用该方法时,我为dice 输入了一个整数数组。当我在dice 数组上运行每个循环时,我将每个数组项命名为die。另外,在我看来,这是一个非常简洁的例子。代码 sn-p 很短,我包含的其余代码大部分只是我收到的错误消息的复制粘贴。
  • 嗯,它可能简洁,但它不是可执行的。一个好的 SSCCE 包括几个输入示例以及预期输出。

标签: ruby


【解决方案1】:

在这一行

/(die)/.match(dice.to_s).length

如果您传递的参数与正则表达式不匹配,则 match 方法返回 nil,从而导致此错误

nil.length
# => NoMethodError: undefined method `length' for nil:NilClass

该方法将返回数组包含每个的次数 里面的数字。

你可以试试这个

a = [1,1,1,2,2,1,3]
a.uniq.map { |x| a.count(x) }
# => [4, 2, 1]
a.uniq.map { |x| {x => a.count(x)} }
# => [{1=>4}, {2=>2}, {3=>1}]

【讨论】:

  • hmm.... 知道为什么在这种情况下不会产生匹配项吗?当我调用 score([5]) 时,我认为 /(die)/ 在功能上等同于 /5/
  • No /(die)/ 实际上匹配 "die",对于像 /#{die}/ 这样的插值将起作用,这将转换为 /(5)/。此外,match 只返回第一个匹配项,并且长度等于匹配项的长度,所以在这种情况下总是1...
  • @lwe 谢谢。这是我希望得到的信息。如果 match 仅返回第一个匹配项,我如何获得一个获取所有匹配项的数组?还有其他方法可以简单地替换 match 吗?
  • @macsplean,看看这个答案stackoverflow.com/questions/80357/…
【解决方案2】:

如果你想计算数组中每个元素的出现次数,那么你可以这样做

def score (dice)
    count_hash = {}
    dice.uniq.each do |die|
      count_hash[die] = dice.count(die)
    end
    count_hash
end

【讨论】:

  • 非常感谢。不过,您知道我为什么会收到这些错误吗?
  • 原因是您对每个不匹配的元素执行to_s。当您与正则表达式匹配时,如果找到匹配项,则返回其索引,否则返回 nil 这就是为什么您收到错误为 undefined method length' for nil:NilClass`
  • 敌人示例 [1,2,3,4] =~ /'1'/ 将返回 nil
  • 第二个错误:您试图将 1 个元素与 x = /(die)/.match(dice).length 等所有元素进行匹配。这类似于 /1/.match([1,2,3,4]) 本身是错误的
【解决方案3】:

如果人们能帮助我理解为什么我的方法行不通,我将不胜感激......

/(die)/ 创建一个Regexp,一个可以与字符串匹配的模式。您的模式匹配并捕获die

Regexp#match 如果存在匹配则返回 MatchData 对象:

/(die)/.match('a string with die')  #=> #<MatchData "die" 1:"die">
#          here's the match: ^^^

或者nil如果没有匹配:

/(die)/.match('a string with dice') #=> nil

您使用的不是字符串,而是整数数组。您可以使用Array#to_s 将此数组转换为字符串:

dice = [5]
dice.to_s  #=> "[5]"

此字符串不包含die,因此match 返回nil

/(die)/.match("[5]") #=> nil

调用nil.length 然后引发NoMethodError

“按原样”传递数组也不起作用,因为match 需要一个字符串:

/(die)/.match([5]) #=> TypeError: no implicit conversion of Array into String

在这里使用Regexp 是行不通的,您必须以另一种方式解决此问题。

【讨论】:

    【解决方案4】:

    这可能是解决问题的最有效的方法:

    a = [1,1,1,2,2,1,3]
    p Hash[a.group_by{|x|x}.map{|key, val| [key,val.size]}]
    #=> {1=>4, 2=>2, 3=>1}
    

    【讨论】:

      【解决方案5】:

      一个可以帮助您实现逻辑的示例

      a = [2,3,2,8,3]
      a.uniq.each {|i| print i, "=>", a.to_s.scan(/#{i}/).length, " times \n" } #=> this works but ugly.
      a.uniq.each {|i| print i, "=>", a.count(i), " times \n" } #=> borrowed from one of the answers.
      
      2=>2 times
      3=>2 times
      8=>1 times
      

      【讨论】:

        【解决方案6】:

        您遇到错误是因为在这两种情况下您都试图将字符串 (5) 与错误的内容匹配。

        这会尝试将die 与转换为字符串的整个数组dice 匹配:

        dice.each do |die|
          x = /(die)/.match(dice.to_s).length
        end
        

        这会尝试将 diedice 数组本身进行匹配:

        dice.each do |die|
          x = /(die)/.match(dice).length
        end
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-11-17
          • 1970-01-01
          • 1970-01-01
          • 2020-02-20
          • 1970-01-01
          • 2022-07-16
          相关资源
          最近更新 更多