我有一个数组:
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]
我被告知从一个你正在迭代的数组中删除是不好的做法。有没有干净的解决方案?
答案 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]
一步一步地做:
.each_with_index
返回一个枚举器,它产生值对及其索引,如[7, 0], [8, 1], [9, 2], ...
.select{...}
选择[x,i]
不能被5 整除的count - i
对(除了count - 5
,count - 10
之外的所有对等等) .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整除的索引,并按它们删除。正如他所说,重要的是按此顺序删除完全。但是为了保护自己免受可能的错误,我认为它更安全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
)独立于数组索引。