我正在尝试使用each_line方法遍历包含许多行的Ruby字符串,但我也想更改它们。我正在使用以下代码,但它似乎不起作用:
string.each_line{|line| line=change_line(line)}
我想,Ruby正在发送我的行的副本而不是行本身,但不幸的是没有方法each_line!。我也试过gsub!方法,使用/^.*$/来检测每一行,但它似乎只调用了change_line方法并用它替换了所有行。任何想法如何做到这一点? 在此先感谢:)
答案 0 :(得分:4)
@azlisum:您没有存储连接的结果。使用:
output = string.lines.map{|line|change_line(line)}.join
比较四种在字符串中逐行处理的方法:
# Inject method (proposed by @steenslang)
output = string.each_line.inject(""){|s, line| s << change_line(line)}
# Join method (proposed by @Lars Haugseth)
output = string.lines.map{|line|change_line(line)}.join
# REGEX method (proposed by @olistik)
output = string.gsub!(/^(.*)$/) {|line| change_line(line)}
# String concatenation += method (proposed by @Erik Hinton)
output = ""
string.each_line{|line| output += change_line(line)}
Benchmark的时间安排:
user system total real
Inject Time: 7.920000 0.010000 7.930000 ( 7.920128)
Join Time: 7.150000 0.010000 7.160000 ( 7.155957)
REGEX Time: 11.660000 0.010000 11.670000 ( 11.661059)
+= Time: 7.080000 0.010000 7.090000 ( 7.076423)
正如@steenslag指出的那样,'s + = a'将生成new string for each concatenation,因此通常不是最佳选择。
因此,考虑到时间,最好的选择是:
output = string.lines.map{|line|change_line(line)}.join
此外,这是更清洁的选择恕我直言。
答案 1 :(得分:3)
您应该尝试使用空白字符串开始,每个字符串穿过字符串,然后将结果推送到空白字符串。
output = ""
string.each_line{|line| output += change_line(line)}
在您的原始示例中,您是对的。你的变化正在发生,但他们并没有在任何地方受到伤害。 Ruby中的Each
默认情况下不会改变任何内容。
答案 2 :(得分:1)
答案 3 :(得分:1)
String#each_line
用于读取字符串中的行,而不是写入它们。您可以使用它来获得您想要的结果:
changed_string = ""
string.each_line{ |line| changed_string += change_line(line) }
答案 4 :(得分:0)
如果你没有给each_line一个块,你将获得一个具有inject方法的枚举器。
str = <<HERE
smestring dsfg
line 2
HERE
res = str.each_line.inject(""){|m,line|m << line.upcase}