質問

私は、Rubyにやや新しいですし、私はそれが私はいくつかの困難暗黙の戻り値がどのように動作するかを理解したのですが非常に直感的な言語であることがわかりましたけれどもます。

私は、Tomcatのログをgrepすると、適切なデータからパイプで区切られた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によって返される結果の数が多い場合を除き、この1であなたがscanを使用する場合があります(アレイ上で作業し、それらを単一の文字列に取り組んでより効率的であるマージ)。

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

他のヒント

Rubyでメソッドの戻り値は、最後の文で返された値です。あなたも、明示的なリターンを持って選ぶことができます。

あなたの例では、最初のスニペットは、文字列outputを返します。第二のスニペットしかしマッチの配列であることが判明した(今最後STMT)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