0

メールを配列に抽出する次の正規表現と関数がありますが、動作している間は最適ではないようです。これを承認する方法について何か提案はありますか?

@emails = []
matches = @text_document.scan(/\+'(\S+@\S+|\{(?:\w+, *)+\w+\}@[\w.-]+)'/i)
matches.each {|m| m[0].split(',').each {|email| @emails << email  }  }

具体的には、ネストされたそれぞれよりも優れたものを探しています。

乾杯

編集私は両方の答えが好きだったので完全に公平にするために、両方に公平な実行をしましたが、 concat は少し速くて短いので、それを答えとしてマークします。

require 'benchmark'

CONSTANT = 1
BenchTimes = 1_000_000
EMAILS = "+'one.emaili@domain.com,another.email@domain.se'"

def email
end

def bm_concat
  emails = []
  EMAILS.scan(/\+'(\S+@\S+|\{(?:\w+, *)+\w+\}@[\w.-]+)'/i) do |matches|
    matches.each {|m| emails.concat(m.split(','))}
  end

end

def bm_inject
  emails = []
  EMAILS.scan(/\+'(\S+@\S+|\{(?:\w+, *)+\w+\}@[\w.-]+)'/i) do |matches|
    matches.inject([]) {|arr, mails| emails.concat(mails.split(',')) }
  end

end

Benchmark.bmbm do |bm|
  bm.report("inject:") { BenchTimes.times { bm_inject } }
  bm.report("concat:") { BenchTimes.times { bm_concat } }
end

次の出力が得られます。

Rehearsal -------------------------------------------
inject:  11.030000   0.060000  11.090000 ( 11.145898)
concat:   9.660000   0.050000   9.710000 (  9.761068)
--------------------------------- total: 20.800000sec

              user     system      total        real
inject:  11.620000   0.060000  11.680000 ( 11.795601)
concat:  10.510000   0.050000  10.560000 ( 10.678999)
4

2 に答える 2

1

これにリファクタリングできますmatches.each

matches.each {|m| @emails.concat(m[0].split(','))}
于 2012-07-31T14:26:59.433 に答える
1

inject を使用 - http://ruby-doc.org/core-1.9.3/Enumerable.html#method-i-inject

@emails = matches.inject([]) do |emails, input| 
  emails += input.first.split(',')
end

参考までに、ブロックに渡される変数、emails は渡された空の配列を参照し、input は、反復処理する match の各要素を参照します。

編集(インジェクトの使い方):

REGEX = /\+'(\S+@\S+|\{(?:\w+, *)+\w+\}@[\w.-]+)'/i
def bm_inject
  emails = EMAILS.scan(REGEX).inject([]) do |arr, mails| 
    arr.concat mails.first.split(',')
  end
end
于 2012-07-31T16:22:57.173 に答える