我想构建一个自定义方法Array#drop_every(n)
(我知道它是猴子修补,我这是为了做作业),它返回一个新的数组,省略了每个第n个元素:
[4, 8, 15, 16, 23, 42].drop_every(2) # [4, 15, 23]
我想用Array#delete_if
实现它,但是通过引用索引而不是元素本身(类似于each_index
)这样的东西:
def drop_every(step)
self.delete_if { |index| index % step == 0 }
end
我该怎么做?我不坚持使用delete_if
,我也看了drop_while
和reject
,欢迎提出其他建议。
答案 0 :(得分:3)
您可以使用返回枚举器的with_index
方法,过滤您的集合,然后删除索引。
class Array
def drop_every(step)
self.each.with_index.select { |_, index| index % step == 0 }.map(&:first)
end
end
[4, 8, 15, 16, 23, 42].drop_every(2) # => [4, 15, 23]
答案 1 :(得分:2)
def drop_every(step)
reject.with_index { |x,i| (i+1) % step == 0 }
end
[4, 8, 15, 16, 23, 42].reject.with_index{|x,i| (i+1) % 2 == 0}
# => [4, 15, 23]
[4, 8, 15, 16, 23, 42].reject.with_index{|x,i| (i+1) % 3 == 0}
# => [4, 8, 16, 23]
答案 2 :(得分:2)
您可以使用values_at
方法有选择地过滤掉您想要的索引。
class Array
def drop_every(step)
self.values_at(*(0...self.size).find_all{ |x| (x+1) % step != 0 })
end
end
我在输入时接受了答案。无论如何我会发布它。
答案 3 :(得分:1)
def drop_every step
delete_if.with_index(1){|_, i| i.%(step).zero?}
end
答案 4 :(得分:1)
class Array
def drop_every(step)
self.each_slice(step).flat_map{|slice| slice[0..-2]}
end
end
p [4, 8, 15, 16, 23, 42].drop_every(2) #=> [4, 15, 23]
答案 5 :(得分:1)
我会扩展Enumerable
mixin:
module Enumerable
def drop_every(step)
return to_enum(:drop_every, step) unless block_given?
each.with_index(1) do |o, i|
yield o unless i % step == 0
end
end
end
(1..10).drop_every(3) { |a| p a }
# outputs below
1
2
4
5
7
8
10