我需要迭代一个数组并将一个提供的块应用于每个元素,并返回该块返回的第一个真值,这意味着我需要在获得真值后立即停止。
下面是我的代码。我是一个红宝石新手,我不确定这个代码是否重新发明轮子。也许有一种库方法或方法可以做到这一点?或者可以简化这段代码?
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'
答案 0 :(得分: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)}
答案 1 :(得分: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 :(得分:1)
这与以下内容重复:Ruby - Array.find, but return the value the block
你想要一张懒惰的地图:
[nil, 1, 2, 3].lazy.map{|i| i && i.to_s}.find{|i| i}
# => "1"
答案 3 :(得分:0)
如果您的正则表达式模式很简单,可以在最后再次应用正则表达式。也可以。
类似的东西:
def find(s,t)
r = RS[s] and r.find{|p| p.match(t)}.try(:match, t)
end
虽然它使一个冗余调用匹配,但更容易理解。
首先,找到您想要的模式,然后使用该模式。