从字符串中提取电子邮件的更多rubyish方式?

时间:2012-07-31 14:06:43

标签: ruby

我有以下正则表达式和函数来提取电子邮件到一个数组,虽然它正在工作它似乎不是我的最佳。有关我如何批准这个的任何建议?

@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)

2 个答案:

答案 0 :(得分:1)

您可以将matches.each重构为:

matches.each {|m| @emails.concat(m[0].split(','))}

答案 1 :(得分:1)

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

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

fyi,传递给块的变量,电子邮件引用传入的空数组,输入引用迭代时的每个匹配元素。

编辑(如何使用注入):

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