我有点新的红宝石,虽然我觉得这是我有一些难以理解的返回值如何隐含的行为非常直观的语言。

我的工作的一个小程序从相关数据的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*?)\]/)

当我运行这段代码我得到以下,这是预期明确时,返回输出的值。

00:00:13,207|06/18|0951714636005|20

然而,如果我改变LineMatcher以下并且不明确地返回输出:

    class LineMatcher
      class << self
        def match(line, regex)
          output = ""
          line.scan(regex).each do |matched|
            output << matched.join("|") << "\n"
          end
        end        
      end
    end

然后得到以下结果:

00:00:13,207
06/18
0951714636005
20

显然,这是不期望的结果。这感觉就像我应该能够摆脱输出变量,但目前还不清楚其中的返回值是从哪里来的。此外,任何其他的建议/出于可读性改进是受欢迎的。

有帮助吗?

解决方案

在红宝石任何语句返回最后计算的表达式的值。 你需要知道的实施和最常用的方法,以确切地知道你的程序将如何行动的行为。

#each将返回迭代的集合。这就是说,下面的代码将返回line.scan(正则表达式)的值。

line.scan(regex).each do |matched|
  output << matched.join("|") << "\n"
end

如果您想返回执行结果,你可以使用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

有您可以根据您的非常特殊的情况下,使用一些有用的方法。在这其中,你可能想使用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

其他提示

在红宝石的方法的返回值是由最后语句返回的值。你可以选择有明确的回报了。

在您的示例中,第一代码段返回字符串output。然而第二个片段返回由each方法(即现在的最后语句),其结果是匹配的阵列返回的值。

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"]

更新:但是这仍然没有在一行说明你的输出。我认为这是一个格式错误,它应该打印每个比赛的另一条线路,因为这是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

我个人找到具有明确的返回更可读的(在这种情况下)的方法

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top