7

配列を反復処理し、提供されたブロックを各要素に適用し、ブロックから返された最初の真の値を返す必要があります。これは、真の値を取得したらすぐに停止する必要があることを意味します。

以下は私のコードです。私は Ruby の初心者であり、このコードが車輪の再発明であるかどうかはわかりません。おそらく、すでにそれを行うことができるライブラリメソッドまたはメソッドがありますか? それとも、このコードを単純化できるのでしょうか?

RS = {
  :x => %w(\d+ a\d+ bb\d+ ccc\d+).map{|x| /^#{x}$/},
  :y => %w(\w+ 1\w+ 22\w+ 333\w+).map{|x| /^#{x}$/}
}.freeze

def find s, t
  r = RS[s]
  if r
    r.each do |p|
      m = p.match t
      return m if m
    end
    nil
  end
end

p find :x, 'bb12345'
4

4 に答える 4

2

ブロックの結果が必要な場合は、この方法で実行できます。これは配列全体を反復しますが、最初の一致の後に一致を評価しません。

def find(s,t)
  RS[s].inject(nil) {|m, p| m || p.match(t)}
end

このようなことを行うと、早期に抜け出すことができます

RS[s].inject(nil) {|m, p| (m && (break m)) || p.match(t)}
于 2013-03-14T20:48:53.333 に答える
1

願わくばまだ現実的です: これは検出を使用した解決策です。ヒットを返す前にどの式が評価されたかを確認できるように、詳細な出力を可能にしました。

def find_match symbol, string , verbose = false, match = nil
  if verbose
    RS.detect{|x,v|x==symbol;v.detect{|re|puts re;match=string.match(/#{re}/)}}
  else
    RS.detect{|x,v|x==symbol;v.detect{|re|match=string.match(/#{re}/)}}
  end
  match
end

p find_match :x, 'bb12345'
p find_match :x, 'ee12345' , true #verbose output
p find_match :x, '12345'
p find_match :y, '22abcd'

#<MatchData "bb12345">
(?-mix:^\d+$)
(?-mix:^a\d+$)
(?-mix:^bb\d+$)
(?-mix:^ccc\d+$)
(?-mix:^\w+$)
#<MatchData "ee12345">
#<MatchData "12345">
#<MatchData "22abcd">
于 2014-03-23T16:49:22.953 に答える
0

正規表現パターンが単純な場合は、最後に正規表現をもう一度適用するだけでよいでしょう。

何かのようなもの:

def find(s,t)
  r = RS[s] and r.find{|p| p.match(t)}.try(:match, t)
end

一致するように 1 つの冗長な呼び出しを行いますが、理解しやすいです。

まず、必要なパターンを見つけて、そのパターンを使用します。

于 2013-03-15T05:58:36.603 に答える