【问题标题】:Simple Ruby loop through array does not iterate completely通过数组的简单 Ruby 循环不会完全迭代
【发布时间】:2014-04-16 23:58:00
【问题描述】:

所以我以为我理解了这一点,但我没有得到预期的输出,所以显然我不明白。

在 Ruby (2.0.0) 中

a = [1,2,3,4]
a.each do |e|
    a.delete(e)
end
a = [2,4]

它似乎没有循环遍历数组中的每个项目。但是,当我简单地输出项目时,它会遍历每个项目。 a.delete(e) 的某些机制会影响迭代。

a = [1,2,3,4]
a.each do |e|
    puts e
end
=> 1
=> 2
=> 3
=> 4

最终,我想在循环中放入一个条件,例如:

a = [1,2,3,4]
a.each do |e|
    if e < 3
        a.delete(e)
    end
end

我怎样才能让这个循环遍历每个项目并删除它?谢谢!

【问题讨论】:

  • 你有什么问题?
  • 澄清问题。
  • 以后,在选择答案之前,请考虑推迟一段时间。一个快速的选择(在这里,发布后仅 15 分钟!)可能会阻止其他可能更好的答案,而且,imo 不尊重那些仍在准备答案的人。
  • 感谢测试版。我已取消选择答案,并会在重新接受之前给它一些时间。
  • 我的评论与@sawa的回答无关,我觉得还不错,得到了我的一票。

标签: ruby arrays


【解决方案1】:

当你迭代一个集合时不要改变它,除非你知道你在做什么

为了您的最终目的,

a = [1,2,3,4]
a.reject!{|e| e < 3 }

【讨论】:

  • 即使你知道自己在做什么,我什至会说不。它不会产生非常可读的代码,尤其是当 ruby​​ 有像 reject!select! 这样可爱的方法时,就像你提到的那样。
  • @PaulRichter 是的,我同意你的看法。这很容易出错,并且严重依赖于实现细节。
  • 我认为 JRuby 在这种情况下会抛出一个java.util.ConcurrentModificationException。至少对于 ArrayHash,它们实际上是由 JRuby 中的 Java 集合支持的。
【解决方案2】:

a = [1,2,3,4]
a.each do |e|
  a.delete(e)
end
a # => [2, 4]

第一次迭代在索引 0 处,e1。删除后,a 变为[2,3,4],下一次迭代位于索引1e3。被删除后,a 变为 [2,4]。下一次迭代将在索引2 处,但由于a 不再那么长,它停止,将a 的值返回为[2, 4]

为了遍历每个项目并删除它,假设没有重复,一个常见的方法是向后迭代。

a = [1,2,3,4]
a.reverse_each do |e|
  a.delete(e)
end
a # => []

a = [1,2,3,4]
a.reverse_each do |e|
  if e < 3
    a.delete(e)
  end
end
a # => [3, 4]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-03
    • 1970-01-01
    • 2013-01-14
    • 2023-02-23
    • 2016-02-25
    • 1970-01-01
    相关资源
    最近更新 更多