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
为什么第一种方法不起作用?或者它可能正在“工作”,我只是不明白为什么我没有得到我所期望的。
答案 0 :(得分:2)
我可以建议一个重构器吗?当你实际上需要each
+ map
(功能)时,你的代码看起来很笨重,因为你正在使用first
循环(命令式)。由于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
答案 1 :(得分:1)
对我来说很好。你实际上是用
调用它吗?result = get_type puts "result: #{result}"
?因为这根本不起作用,虽然我假设你发布的时候有一个吃过的换行。