请帮助纠正我对这个集合迭代、匹配和删除的误解:

Please help correct my misunderstanding of this collection iteration, matching and deletion:

我正在尝试遍历字符串数组并删除首字母不是元音的字符串。我知道有更简洁的方法可以实现这一目标,例如#select,但我不明白为什么下面的不起作用。有人可以解释一下这段代码有什么问题吗:

def delete_unless_1st_letter_is_vowel(array)
  array.each do |element|
    first_letter = element[0]
    if !first_letter.match?(/[aeiou]/)
      array.delete(element)
    end
  end
end

array = %w(knit taleb know high london alpha)

returns;

taleb
high
alpha

我觉得它应该删除除 alpha 之外的所有数组元素。我误会了什么?

那是因为您在迭代它的同时从 array 中删除了元素;

第一次迭代:

element = "knit"
array = ["knit", "taleb", "know", "high", "london", "alpha"]

你删除“编织”,剩下的数组是["taleb", "know", "high", "london", "alpha"]

第二次迭代。该块继续工作,但现在轮到从 array 持有的当前值生成第二个元素,即“知道”;

element = "know"
array = ["taleb", "high", "london", "alpha"]

第三次迭代。同样的故事,现在轮到第三个元素,现在指向“伦敦”:

element = "london"
array = ["taleb", "high", "alpha"]

第四次迭代。没有第四次迭代,您删除了与当前索引相同数量的元素。

当你使用每个时,它 returns 接收者,所以你得到 ["taleb", "high", "alpha"]


为了简单起见,我认为在这种情况下grep就足够了:

def delete_unless_1st_letter_is_vowel(array)
  array.grep(/^[aeiou]/)
end

并且要避免改变对象,即使编程语言让你全部去做。