删除数组中的值在Ruby中以反向方式遍历它

时间:2013-10-11 11:16:01

标签: ruby

我有一个数组:

arr = [7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 19, 20, 21, 22, 23]

我希望通过删除-5的每一步来修改我的数组,即arr[-5], arr[-10], arr[-15],以便删除后的原始数组arr等于:

arr = [8, 9, 10, 11, 14, 15, 16, 17, 20, 21, 22, 23]

我被告知从一个你正在迭代的数组中删除是不好的做法。有没有干净的解决方案?

5 个答案:

答案 0 :(得分:2)

修改 @tihom 的答案,不依赖于唯一性,而是使用"How to map with index in Ruby?"中的一些想法:

>> arr.each_with_index.select{ |x, i| (arr.count-i)%5 != 0 }.map{ |x,i| x }
=> [8, 9, 10, 11, 14, 15, 16, 17, 20, 21, 22, 23]

一步一步地做:

  1. .each_with_index返回一个枚举器,它产生值对及其索引,如[7, 0], [8, 1], [9, 2], ...
  2. .select{...}选择[x,i]不能被5 整除的count - i对(除了count - 5count - 10之外的所有对等等)
  3. .map{ |x,i| x }将每对转换为第一个元素。
  4. 不是最有效的,但至少是明确的,我认为

    <强>奖金:

    确定最好通过某些转换(功能样式)创建一个新数组,而不是就地修改它,但如果你坚持“就地”,这里是 @sawa 的答案的修改,没有硬编码数字:

    >> (-arr.count..-5).select {|i| i % 5 == 0}.each{|i| arr.delete_at(i)}
    => [-15, -10, -5]
    >> arr
    => [8, 9, 10, 11, 14, 15, 16, 17, 20, 21, 22, 23]
    

    这里我们有一个范围从-size到-5,只选择可被5整除的索引,并按它们删除。正如他所说,重要的是按此顺序删除完全。但是为了保护自己免受可能的错误,我认为它更安全yo 永远不会从你正在迭代的数组中删除而是生成一个新的数组(就像在第一种方法中一样)。为何复杂化? ;)

答案 1 :(得分:1)

这是一个简单的解决方案:

p arr.reverse.each_slice(5).map{|x|x[0..-2]}.flatten.reverse
# => [8, 9, 10, 11, 14, 15, 16, 17, 20, 21, 22, 23]

答案 2 :(得分:1)

arr.reject.with_index{|x,i| (i-arr.count) % 5 == 0 }
 => [8, 9, 10, 11, 14, 15, 16, 17, 20, 21, 22, 23] 

答案 3 :(得分:1)

在计算索引的同一侧迭代时修改数组很复杂。换句话说,当你有正指数时,你不应该在修改时从头到尾迭代;如果你有负指数,你不应该从尾部迭代到头部。否则,没有问题。

由于您有负指数,因此从头部向尾部进行修改至关重要。

[-15, -10, -5].each{|i| arr.delete_at(i)}
# => [8, 9, 10, 11, 14, 15, 16, 17, 20, 21, 22, 23]

答案 4 :(得分:1)

根据答案https://stackoverflow.com/a/19317883/908515

arr.reverse.reject.with_index { | _, i | (i + 1) % 5 == 0 }.reverse
# i.e. arr.reverse.drop_every(5).reverse

如果要在原地修改原始数组,可以执行

arr.reverse!.reject!.with_index { | _, i | (i + 1) % 5 == 0 }.reverse!

这是安全的,因为枚举器索引(i)独立于数组索引。