2013-03-14 54 views
6

我需要迭代数组并将所提供的块应用于每个元素,并返回该块返回的第一个真值,这意味着我需要立即停止,只要我得到真正的价值。找到数组中的第一个元素,其中块返回true并返回块的返回值

下面是我的代码。我是一个红宝石新手,我不确定这个代码是否会重新发明轮子。也许有一个库方法可以做到这一点?或者可能是这段代码可以简化?

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' 
+1

你正在寻找的东西像['可枚举#find'(HTTP:// ruby​​- doc.org/core-2.0/Enumerable.html#method-i-find)返回块返回的内容而不是哪个元素导致块返回真值? – 2013-03-14 21:24:20

+0

@ muistooshort,是的,谢谢 – akonsu 2013-03-14 22:32:47

+0

我认为你正在做的是关于所有的事情。你可以把它修改得很好,猴子将它修改为Enumerable,但这就是它。 – 2013-03-14 23:20:59

回答

1

希望仍然是实际的:在这里使用detect的解决方案,我可以将输出详细化,以便在返回命中之前查看哪些表达式被评估。

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"> 
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)} 
+0

谢谢。在这种情况下,我需要返回'true',因为这是块返回的值。 – akonsu 2013-03-14 20:51:08

0

的东西,如果你的正则表达式模式是简单的,你可以再次在最后应用正则表达式,也许。

喜欢的东西:

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

虽然它使一个冗余呼叫匹配,就比较容易理解了。

首先,找到你想要的模式,然后使用该模式。

相关问题