如何在Array#delete_if中引用元素的索引
我想构建一个自定义方法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
,欢迎其他建议。
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]
您可以使用返回枚举器的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]
您可以使用values_at
方法有选择地筛选出所需的索引。
class Array def drop_every(step) self.values_at(*(0...self.size).find_all{ |x| (x+1) % step != 0 }) end end
在我输入时,答案被接受了。 无论如何我会发布它。
def drop_every step delete_if.with_index(1){|_, i| i.%(step).zero?} end
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]
我将扩展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| pa } # outputs below 1 2 4 5 7 8 10