返回条件值的`find`,而不是元素值

时间:2016-04-01 15:51:31

标签: ruby enumerator

我正在扫描source中满足条件的元素。这种情况通常(但不总是)是正则表达式匹配。我正在寻找一个find的版本,它返回条件的结果,而不是原始元素。使用find,我必须重新计算成功元素的标准。

我研究出的最好成绩沿着这条线运行:

source.find {|e| if (m = e.match(/(e.)/)); break m[0]; end}

为了避免使用分号提示Rubocop抱怨多语句行,我更喜欢写如下:

source.find {|e| break m[0] if (m = e.match(/(e.)/))}

但Ruby无法应对前向引用(我没有足够的扭曲来重用e的{​​{1}}。

使用短切割做这项工作是否更优雅?

2 个答案:

答案 0 :(得分:1)

由于您有break,因此您无需find来破解。使用each

source.each {|e| m = e[/e./] and break m}

答案 1 :(得分:0)

虽然我更喜欢@sawa建议的内容,但您可以使用实例变量:

["dog", "cat", "emu", "pig"].find { |e| $da_match = e[/(e.)/] }
  #=> "emu"
$da_match 
  #=> "em"

或者,对于你的正则表达式:

["dog", "cat", "emu", "pig"].find { |e| e =~ /(e.)/ }
  #=> "emu" 
$1
  #=> "em" 

如果正则表达式r没有(或可能没有)外部捕获组,您可以像这样添加一个:/(#{r})/。例如,

r0 = /e./
r1 = /(#{r0})/
  #/((?-mix:e.))/

["dog", "cat", "emu", "pig"].find { |e| e =~ r1 }
  #=> "emu" 
$1 
  #=> "em" 

根据正则表达式的使用方式,这可能不起作用。如果(原始)正则表达式包含一个或多个捕获组,则捕获组1将成为捕获组2,依此类推。因此,如果在正则表达式或后续代码中引用其中一个捕获组的内容,则将获得不正确的值。但是,如果您使用了命名捕获组并为要添加的外部名称保留了名称,那么这不会成为问题:

["dog", "cat", "emu", "pig"].find { |e| e =~ /(?<outer>#{/e./})/ }
  #=> "emu" 
$~[:outer]
  #=> "em"

$~是一个包含最新MatchData对象的全局变量。

相关问题