count方法如何在Ruby中运行?

时间:2017-10-01 16:07:34

标签: ruby string

我很难理解Ruby docs中的以下代码段:

a = "hello world"
a.count "lo"                   #=> 5
a.count "lo", "o"              #=> 2
a.count "hello", "^l"          #=> 4
a.count "ej-m"                 #=> 4

"hello^world".count "\\^aeiou" #=> 4
"hello-world".count "a\\-eo"   #=> 4

尤其是此代码a.count "ej-m"。任何人都可以解释它是如何工作的吗?

3 个答案:

答案 0 :(得分:5)

想象一下由[包裹的“模式”字符串和正则表达式语法中的],它们与每个字符匹配。

所以,如果我们将a = "hello world"分成字符:

[1] pry(main)> a = "hello world"
=> "hello world"
[2] pry(main)> a.split('')
=> ["h", "e", "l", "l", "o", " ", "w", "o", "r", "l", "d"]

将“ej-m”转换为包含[]的正则表达式,我们得到/[ej-m]/ - 这意味着'e'或来自'j'的任何字符到'm'(包括两者):

[3] pry(main)> a.split('').select{|c| c=~ /[ej-m]/}
=> ["e", "l", "l", "l"]

我们有4场比赛 - 这也是你得到的结果。实际上a.count "ej-m"相当于:

[4] pry(main)> a.split('').count{|c| c=~ /[ej-m]/}
=> 4

方法的多个参数在匹配项之间只有and

[5] pry(main)> a.split('').count{|c| c =~ /[hello]/ and c =~ /[^l]/}
=> 4

答案 1 :(得分:2)

The sequence c1-c2 means all characters between c1 and c2. 因此,您提供的是一个范围,基本上它会计算该范围内的哪些字符(> = c1&&< = c2) 即:

a = "hello world"
a.count "a-z"
=> 10 
a.count "o-w"
=> 4  #(o, o, r, w)
a.count "e-l"
=> 5  #(h, e, l, l, l)

答案 2 :(得分:2)

我们找到了

"hello world".count("ej-m")       #=> 4 (_ell_____l_)

仔细检查String#count的文档。

以下是count如何实施以处理与模式"ej-m"非常相似的模式。

def count_letters(str, pattern) 
  idx = pattern[1..-2].index('-')
  if idx
    idx += 1
    before, after = pattern[idx-1], pattern[idx+1]
    pattern[idx-1..idx+1] = (before..after).to_a.join
  end
  str.each_char.sum { |c| pattern.include?(c) ? 1 : 0 }
end

count_letters(str, pattern)       #=> 4 (_ell_____l_)

但是,String#count也必须执行以下操作。

允许模式中的多个范围

"hello1world".count("e0-9j-mv-x") #=> 6 (_ell__1_w__l_)

如果模式以字符'^'开头,则计算与模式的其余部分不匹配的字符数

"hello world".count("^ej-m")      #=> 7 (h___o*wor_d) * = space to count
"hello^world".count("e^j-m")      #=> 5 (_ell_^___l_)
"hello world".count("\^ej-m")     #=> 7 (h___o*wor_d) * = space to count

请注意,在字符串开头转义'^'没有任何区别。

匹配连字符

"hello-world".count("ej-m-")      #=> 5 (_ell_-___l_)
"hello-world".count("-ej-m")      #=> 5 (_ell_-___l_)
"hello-world".count("ej\-m")      #=> 4 (_ell____l_)

请注意,转义不是模式的第一个或最后一个字符的连字符没有区别。

匹配反斜杠

'hello\world'.count("ej-m\\")     #=> 5 (_ell_\___l_)
'hello\world'.count("\\ej-m")     #=> 4 (_ell____l_)

请注意,忽略字符串开头的反斜杠。

上述一些结果(Ruby v2.4)似乎与文档不一致。