csa*_*uel 18 ruby readability return implicit
我对Ruby有点新鲜,虽然我发现它是一种非常直观的语言,但我很难理解隐式返回值的行为方式.
我正在开发一个小程序来grep Tomcat日志并从相关数据生成管道分隔的CSV文件.这是我用来从日志条目生成行的简化示例.
class LineMatcher
class << self
def match(line, regex)
output = ""
line.scan(regex).each do |matched|
output << matched.join("|") << "\n"
end
return output
end
end
end
puts LineMatcher.match("00:00:13,207 06/18 INFO stateLogger - TerminationRequest[accountId=AccountId@66679198[accountNumber=0951714636005,srNumber=20]",
/^(\d{2}:\d{2}:\d{2},\d{3}).*?(\d{2}\/\d{2}).*?\[accountNumber=(\d*?),srNumber=(\d*?)\]/)
Run Code Online (Sandbox Code Playgroud)
当我运行这段代码时,我得到了以下内容,这是显式返回输出值时的预期结果.
00:00:13,207|06/18|0951714636005|20
Run Code Online (Sandbox Code Playgroud)
但是,如果我将LineMatcher更改为以下内容并且不显式返回输出:
class LineMatcher
class << self
def match(line, regex)
output = ""
line.scan(regex).each do |matched|
output << matched.join("|") << "\n"
end
end
end
end
Run Code Online (Sandbox Code Playgroud)
然后我得到以下结果:
00:00:13,207
06/18
0951714636005
20
Run Code Online (Sandbox Code Playgroud)
显然,这不是理想的结果.感觉我应该能够摆脱输出变量,但不清楚返回值的来源.此外,欢迎任何其他可读性的建议/改进.
Sim*_*tti 23
ruby中的任何语句都返回上次计算的表达式的值.您需要了解最常用方法的实现和行为,以便准确了解您的程序将如何操作.
#each
返回您迭代的集合.也就是说,以下代码将返回line.scan(regexp)的值.
line.scan(regex).each do |matched|
output << matched.join("|") << "\n"
end
Run Code Online (Sandbox Code Playgroud)
如果要返回执行结果,可以使用map
,作为each
但返回修改后的集合.
class LineMatcher
class << self
def match(line, regex)
line.scan(regex).map do |matched|
matched.join("|")
end.join("\n") # remember the final join
end
end
end
Run Code Online (Sandbox Code Playgroud)
根据您的具体情况,您可以使用几种有用的方法.在这个中你可能想要使用,inject
除非返回的结果数量scan
很高(处理数组然后合并它们比处理单个字符串更有效).
class LineMatcher
class << self
def match(line, regex)
line.scan(regex).inject("") do |output, matched|
output << matched.join("|") << "\n"
end
end
end
end
Run Code Online (Sandbox Code Playgroud)
Gis*_*shu 14
在ruby中,方法的返回值是最后一个语句返回的值.您也可以选择明确的退货.
在您的示例中,第一个代码段返回字符串output
.然而,第二个片段返回each
方法返回的值(现在是最后一个stmt),结果是一个匹配数组.
irb(main):014:0> "StackOverflow Meta".scan(/[aeiou]\w/).each do |match|
irb(main):015:1* s << match
irb(main):016:1> end
=> ["ac", "er", "ow", "et"]
Run Code Online (Sandbox Code Playgroud)
更新:但是仍然无法解释单行输出.我认为这是格式错误,它应该在不同的行上打印每个匹配,因为这是puts
打印数组的方式.一点点代码可以比我更好地解释它..
irb(main):003:0> one_to_three = (1..3).to_a
=> [1, 2, 3]
irb(main):004:0> puts one_to_three
1
2
3
=> nil
Run Code Online (Sandbox Code Playgroud)
我个人发现你的方法与显式返回更具可读性(在这种情况下)