在阵列上使用匹配时出现问题

时间:2013-10-28 08:03:12

标签: ruby

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

所以我首先尝试这种方法

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

并使用score ([5])调用它,期望输出为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>'

真的不确定我应该如何完成这种匹配。

6 个答案:

答案 0 :(得分:2)

在这一行

/(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}]

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

  

如果大家能帮助我理解为什么我的方式不起作用,我会很感激...

/(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在这里不起作用,你必须以另一种方式解决这个问题。

答案 3 :(得分:1)

这可能是解决问题最红宝石的方法:

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}

答案 4 :(得分:0)

可能有助于您实现逻辑的示例

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

答案 5 :(得分:0)

你遇到错误,因为在这两种情况下你都试图将字符串(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