【问题标题】:Ruby: Skip element in loop if an exception is raisedRuby:如果引发异常,则跳过循环中的元素
【发布时间】:2016-05-23 10:53:28
【问题描述】:

我有以下方法:

def fetch_something
  @fetch_something ||= array_of_names.inject({}) do |results, name|
    begin
      results[name] = fetch_value!(name)
    rescue NoMethodError, RuntimeError
      next
    end

    results
  end
end

为了它的目的:它为给定的name 获取一个可能引发错误的值,在这种情况下它将忽略name 并尝试下一个。

虽然这工作正常,但我从 Rubocop 收到一条错误消息:

Lint/NextWithoutAccumulator:将 next 与累加器参数一起使用 减少。

谷歌搜索该错误导致我到http://www.rubydoc.info/gems/rubocop/0.36.0/RuboCop/Cop/Lint/NextWithoutAccumulator,它说不要省略累加器,这将导致方法如下所示:

def fetch_something
  @fetch_something ||= array_of_names.inject({}) do |results, name|
    begin
      results[name] = fetch_value!(name)
    rescue NoMethodError, RuntimeError
      next(name)
    end

    results
  end
end

问题是,这个改变打破了原本的工作方法。关于如何解决这个问题的任何想法?

更新:示范示例:
array_of_names = ['name1','name2','name3']

def fetch_value!(name)
  # some code that raises an error if the name doesn't correspond to anything
end

fetch_something

# => {'name1' => {key1: 'value1', ...}, 'name3' => {key3: 'value3', ...}}
# 'name2' is missing since it wasn't found durcing the lookup

【问题讨论】:

  • 试试next(results) 怎么样?
  • @user12341234 这也破坏了它。
  • 也许您可以显示示例输入/输出来衡量预期的行为?
  • @user12341234 添加示例
  • Severin,请参阅@user12341234 答案。我不知道,结果哈希中不需要没有值的键。

标签: ruby-on-rails ruby loops ruby-on-rails-4 rubocop


【解决方案1】:

使用您的示例代码,next(results) 似乎确实为我解决了这个问题。我使用了一些测试代码,它会抛出 KeyError 而不是 NoMethodErrorRuntimeError,但想法仍然相同:

@array_of_names = ['name1','name2','name3']

def fetch_value!(name)
  {'name1' => 'n1', 'name3' => 'n3'}.fetch(name)
end

def fetch_something
  @fetch_something ||= @array_of_names.inject({}) do |results, name|
    begin
      results[name] = fetch_value!(name)
    rescue NoMethodError, RuntimeError, KeyError
      next(results)
    end

    results
  end
end

p fetch_something

此代码输出:

{"name1"=>"n1", "name3"=>"n3"}

另外,我同意@Алексей Кузнецов 的观点,即each_with_object 可能是当您的块代码改变您尝试构建的数据结构时要走的路。所以我对fetch_something 的首选实现可能更像这样:

def fetch_something
  @fetch_something ||= @array_of_names.each_with_object({}) do |name, results|
    begin
      results[name] = fetch_value!(name)
    rescue NoMethodError, RuntimeError, KeyError
      # error handling
    end
  end
end

请注意,在我的示例中,begin/end分配给results[name],而@Алексей Кузнецов 的示例每次都会将nil 分配给哈希发生异常。

【讨论】:

    【解决方案2】:

    只需使用 each_with_object

    def fetch_something
      @fetch_something ||= array_of_names.each_with_object({}) do |name, results|
        results[name] ||= begin
                            fetch_value!(name)
                          rescue NoMethodError, RuntimeError
                          end
      end
    end
    

    【讨论】:

    • 这也破坏了它的原始功能。
    猜你喜欢
    • 2012-03-02
    • 1970-01-01
    • 1970-01-01
    • 2012-03-12
    • 2011-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多