从嵌套的每个块返回单个值,尝试使用'return'

时间:2011-03-07 15:55:04

标签: ruby

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

为什么第一种方法不起作用?或者它可能正在“工作”,我只是不明白为什么我没有得到我所期望的。

2 个答案:

答案 0 :(得分:2)

我可以建议一个重构器吗?当你实际上需要each + map(功能)时,你的代码看起来很笨重,因为你正在使用first循环(命令式)。由于Ruby可枚举不是懒惰,因此效率低下,因此人们通常构建抽象Enumerable#map_detect(或find_yield,或find_firstmap_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}"

?因为这根本不起作用,虽然我假设你发布的时候有一个吃过的换行。