2

我有一个数组:

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]

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

4

5 回答 5

2

只是对@tihom答案的修改,不依赖于唯一性,而是使用“如何在 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{...}选择那些不能被 5 整除的对[x,i]count - i除了,count - 5count - 10
  3. .map{ |x,i| x }将每一对转换为其第一个元素。

我认为不是最有效的,但至少很清楚

奖金:

确信通过一些转换(以功能样式)创建一个新数组比就地修改它更好,但是如果你坚持“就地”,这里是@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 整除的索引,然后被它们删除。正如他所说,在这里按此顺序准确删除很重要。但仍然为了保护自己免受可能的错误,我认为永远不要从正在迭代的数组中删除而是生成一个新数组(如第一种方法)更安全。为什么复杂?;)

于 2013-10-11T14:17:39.043 回答
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]
于 2013-10-11T11:28:42.313 回答
1
arr.reject.with_index{|x,i| (i-arr.count) % 5 == 0 }
 => [8, 9, 10, 11, 14, 15, 16, 17, 20, 21, 22, 23] 
于 2013-10-11T11:28:49.037 回答
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器索引 ( ) 独立于数组索引。

于 2013-10-11T13:31:23.320 回答
1

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

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

[-15, -10, -5].each{|i| arr.delete_at(i)}
# => [8, 9, 10, 11, 14, 15, 16, 17, 20, 21, 22, 23]
于 2013-10-11T13:13:58.857 回答