2011-03-07 63 views
0
def get_type 
    x = [{:type=>'A', :patterns=>['foo.*']}, {:type=>'B', :patterns=>['bar.*']}] 

    name = 'foo.txt' 

    result = x.each { |item| 
    item[:patterns].each { |regex| 
     puts "Checking #{regex} against #{name}" 
     if !name.match(regex).nil? 
     puts "Found match: #{item[:type]}" 
     return item[:type] 
     end 
    } 
    } 
end 

result = get_type 
puts "result: #{result}" 

預期輸出:從一個嵌套的每個塊返回一個值,試圖用「迴歸」

Checking foo.* against foo.txt 
Found match: A 
result: A 

然而,所有我看到的是:

Checking foo.* against foo.txt 
Found match: A 

我目前的解決辦法是這樣的:

def get_type 
    x = [{:type=>'A', :patterns=>['foo.*']}, {:type=>'B', :patterns=>['bar.*']}] 

    name = 'foo.txt' 

    result = [] 
    x.each { |item| 
    item[:patterns].each { |regex| 
     puts "Checking #{regex} against #{name}" 
     if !name.match(regex).nil? 
     puts "Found match: #{item[:type]}" 
     result << item[:type] 
     end 
    } 
    } 
    result[0] unless result.empty? 
end 

爲什麼第一個ap打工?或者可能是'工作',我只是不明白爲什麼我沒有得到我所期望的。

回答

1

適合我。你真的用它調用它嗎?

result = get_type puts "result: #{result}" 

?因爲這根本不應該工作,儘管我假設有一個換行符在你發佈時會被吃掉。

+0

你說得對。我還有其他一些錯字。我發現的是,如果沒有匹配,那麼「結果」將被設置爲等於'x'數組。這是我需要注意的一個條件。 – codecraig 2011-03-07 16:14:39

2

我可以提出重構嗎?您的代碼看起來有點笨重,因爲當您實際上需要map + first(功能)時,您正在使用each循環(必要)。隨着Ruby可枚舉不偷懶,這將是低效的,所以人們通常建立在抽象Enumerable#map_detect(或find_yield,或find_first,或map_first):

def get_type_using_map_detect(name) 
    xs = [{:type => 'A', :patterns => ['foo.*']}, {:type => 'B', :patterns => ['bar.*']}] 
    xs.map_detect do |item| 
    item[:patterns].map_detect do |regex| 
     item[:type] if name.match(regex) 
    end 
    end 
end 

這是一個可能的實施方法:

module Enumerable 
    # Like Enumerable#map but return only the first non-nil value 
    def map_detect 
    self.each do |item| 
     if result = (yield item) 
     return result 
     end 
    end 
    nil 
    end 
end