ruby regex scan vs .split方法

时间:2013-04-17 17:32:56

标签: ruby regex

我正在尝试构建一种方法,你可以取出每个单词的第一个字母并将其大写。我把它写成

def titleize(name)
   name.scan(/\w+/) { |x| x.capitalize! }
end

它只是无法正常工作。它不会大写和写信。我做了一些搜索,最终找到答案Capitalizing titles。它写成

def titleize(name)
   name.split(" ").each { |x| x.capitalize! }.join(" ")
end

为什么我的代码根本没有大写呢?如果我添加了一个put语句并将其写为

def titleize(name)
   name.scan(/\w+/) { |x| puts x.capitalize! }
end

它会用大写字母输出“hi there”但是=>仍然只是“喜欢那里”我错过了什么?

4 个答案:

答案 0 :(得分:2)

更正后的代码:

def titleize(name)
   name.scan(/\w+/).each { |x| x.capitalize! }.join(' ')
end

p titleize("ayan roy") #=>"Ayan Roy"

让我们看看为什么你的工作不起作用:

def titleize(name)
   name.scan(/\w+/) 
end

p titleize("ayan roy") #=>["ayan", "roy"]

现在,您的行name.scan(/\w+/) { |x| x.capitalize! }x将作为"ayan", "roy"传递。现在看下面的内容:

def titleize(name)
   name.scan(/\w+/) { |x| p x.capitalize!  } 
end

p titleize("ayan roy")

输出:

"Ayan"
"Roy"
"ayan roy"

正如String#scan所说:

  

扫描(模式){|匹配,... | block}→str - 如果给出了块,则scan将返回调用它的receiver。两种形式都通过str迭代,匹配模式(可能是Regexp或String)。对于每个匹配,生成结果并将其添加到结果数组或传递给块。

答案 1 :(得分:2)

scan返回/产生新字符串,永远不会修改源字符串。也许你想要gsub

def titleize(name)
  name.gsub(/\w+/) {|x| x.capitalize }
end

或者更好地使用titleize gem中可能更正确的实现。

答案 2 :(得分:1)

您的代码不起作用,因为#scan返回新的String对象,这些对象是Regexp的结果并将它们传递给块。所以在你的方法中你基本上接受了这些新对象,通过调用#capitalize!来改变它们,但之后从未在任何地方使用它们。

你应该这样做:

def titleize(name)
  name.scan(/\w+/).each { |x| x.capitalize! }.join(' ')
end

但这对我来说似乎更具可读性:

def titleize2(name)
  name.split(' ').each { |w| w.capitalize! }.join(' ')
end

但请注意,这些方法不会改变传递的原始参数。

答案 3 :(得分:0)

scan的块形式返回原始字符串,无论您在块中执行什么操作。 (我想你可以通过直接引用它来改变块中的原始字符串,但不建议改变你正在迭代的东西。)而是做你的split变体,而不是eachcollect后跟join

name.split(" ").collect { |x| x.capitalize }.join(" ")

这适用于包含数字和标点符号的标题。