Ruby: 如果引发异常则跳过循环中的元素
Ruby: Skip element in loop if an exception is raised
我有以下方法:
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: Use next with an accumulator argument in
a reduce.
谷歌搜索该错误导致我 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
只需使用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
使用您的示例代码,next(results)
似乎确实解决了我的问题。我使用了一些抛出 KeyError
而不是 NoMethodError
或 RuntimeError
的测试代码,但想法仍然相同:
@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
分配给散列。
我有以下方法:
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: Use next with an accumulator argument in a reduce.
谷歌搜索该错误导致我 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
只需使用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
使用您的示例代码,next(results)
似乎确实解决了我的问题。我使用了一些抛出 KeyError
而不是 NoMethodError
或 RuntimeError
的测试代码,但想法仍然相同:
@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
分配给散列。