2013-03-14 128 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 

雖然它使一個冗餘呼叫匹配,就比較容易理解了。

首先,找到你想要的模式,然後使用該模式。

相關問題