【问题标题】:find first element in array for which block returns true and return the block's return value找到数组中第一个元素,块返回true并返回块的返回值
【发布时间】:2013-03-14 20:42:58
【问题描述】:

我需要遍历一个数组并将提供的块应用于每个元素,并返回该块返回的第一个真值,这意味着我需要在获得真值后立即停止。

下面是我的代码。我是一个红宝石新手,我不确定这段代码是否在重新发明轮子。也许已经有一个或多个库方法可以做到这一点?还是可以简化这段代码?

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'

【问题讨论】:

  • 您正在寻找类似Enumerable#find 的东西,它返回块返回的内容,而不是哪个元素导致块返回真值?
  • @muistooshort,是的,谢谢
  • 我认为你所做的是关于所有的事情。你可以把它美化一下,然后猴子把它修补到 Enumerable 中,仅此而已。

标签: ruby


【解决方案1】:

如果你想要块的结果,你可以这样做。这将遍历整个数组,但不会在第一个匹配之后评估任何匹配。

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)}

【讨论】:

  • 谢谢。在这种情况下我需要返回true,因为这是块返回的值。
【解决方案2】:

这是重复的: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】:

    希望仍然是实际的:这里是使用检测的解决方案,我可以详细说明输出,以便您可以查看在返回命中之前评估了哪些表达式。

    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">
    

    【讨论】:

      【解决方案4】:

      如果您的正则表达式模式很简单,您可以在最后再次应用正则表达式,也许。

      类似:

      def find(s,t)
        r = RS[s] and r.find{|p| p.match(t)}.try(:match, t)
      end
      

      虽然它做了一个冗余调用来匹配,但更容易理解。

      首先,找到你想要的模式,然后使用那个模式。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多