ruby 跳过Enumerable#collect中的迭代

jchrr9hc  于 2022-11-22  发布在  Ruby
关注(0)|答案(6)|浏览(131)
(1..4).collect do |x|
  next if x == 3
  x + 1
end # => [2, 3, nil, 5]
    # desired => [2, 3, 5]

如果满足next的条件,collect会将nil放入数组中,而我尝试做的是,如果满足条件,则将 no 元素放入返回的数组中。如果不对返回的数组调用delete_if { |x| x == nil },这是否可行?
我的代码摘录是高度抽象的,所以寻找一个通用的解决方案的问题。

bxgwgixi

bxgwgixi1#

有 一 个 方法 Enumerable#reject , 它 的 作用 就是 :

(1..4).reject{|x| x == 3}.collect{|x| x + 1}

中 的 每 一 个
直接 使用 一 个 方法 的 输出 作为 另 一 个 方法 的 输入 的 做法 被 称为 * 方法 链接 * , 在 Ruby 中 非常 常见 。
顺便 说 一 句 , map ( 或 collect ) 用于 将 可 枚举 的 输入 直接 Map 到 输出 。 如果 需要 输出 不同 数量 的 元素 , 可能 需要 Enumerable 的 另 一 个 方法 。
编辑 : 如果 你 对 某些 元素 迭代 两 次 感到 困扰 , 你 可以 使用 基于 inject ( 或 类似 的 each_with_object ) 的 解决 方案 :

(1..4).each_with_object([]){|x,a| a << x + 1 unless x == 3}

格式

eoigrqb6

eoigrqb62#

我只需要对结果数组调用.compact,它会删除数组中nil的所有示例。如果你想让它修改现有数组(没有理由不这样做),请使用.compact!

(1..4).collect do |x|
  next if x == 3
  x
end.compact!
igetnqfo

igetnqfo3#

在Ruby 2.7+中,可以使用filter_map来实现这个目的。
返回一个数组,其中包含块返回的真实元素。

(0..9).filter_map {|i| i * 2 if i.even? }   #=> [0, 4, 8, 12, 16]
{foo: 0, bar: 1, baz: 2}.filter_map {|key, value| key if value.even? }  #=> [:foo, :baz]

对于问题中的示例:(1..4).filter_map { |x| x + 1 unless x == 3 } .
请参阅this post,了解与替代方法的比较,包括性能指标评测。

4zcjmb1e

4zcjmb1e4#

只是个建议,你为什么不这样做:

result = []
(1..4).each do |x|
  next if x == 3
  result << x
end
result # => [1, 2, 4]

这样你就保存了另一次迭代来从数组中删除nil元素。希望它能帮助你=)

ccrfmcuu

ccrfmcuu5#

我建议用途:

(1..4).to_a.delete_if {|x| x == 3}

而不是collect + next语句。

u7up0aaq

u7up0aaq6#

您 可以 将 决策 引入 一 个 helper 方法 , 并 通过 Enumerable#reduce 使用 它 :

def potentially_keep(list, i)
  if i === 3
    list
  else
    list.push i
  end
end
# => :potentially_keep

(1..4).reduce([]) { |memo, i| potentially_keep(memo, i) }
# => [1, 2, 4]

中 的 每 一 个

相关问题