【问题标题】:A `find` that returns the condition value, not the element value一个返回条件值而不是元素值的`find`
【发布时间】:2016-04-01 15:51:31
【问题描述】:

我正在扫描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 重复用于m)。

有什么更优雅的方法可以通过捷径完成这项工作吗?

【问题讨论】:

  • 如果您不知道,您可以为答案投票并选择您认为最有帮助的答案。

标签: ruby enumerator


【解决方案1】:

既然你有break,你就不需要find 来破解。使用each

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

【讨论】:

  • 太全神贯注于“寻找”和“注入”的聪明才智。谢谢。
【解决方案2】:

虽然我更喜欢@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 对象的全局变量。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-12
    • 2020-06-12
    • 2020-02-23
    • 1970-01-01
    • 2021-04-28
    • 2014-06-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多