2

我想构建一个自定义方法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其他建议。

4

6 回答 6

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]
于 2013-10-11T12:12:25.383 回答
2

您可以使用该values_at方法有选择地过滤掉您想要的索引。

class Array
  def drop_every(step)
    self.values_at(*(0...self.size).find_all{ |x| (x+1) % step != 0 })
  end    
end

我在打字时接受了答案。无论如何我都会发布它。

于 2013-10-11T12:45:03.753 回答
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] 
于 2013-10-11T12:13:28.433 回答
1

我会扩展Enumerablemixin:

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
于 2013-10-14T08:44:15.153 回答
1
def drop_every step
  delete_if.with_index(1){|_, i| i.%(step).zero?}
end
于 2013-10-11T13:05:14.037 回答
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]
于 2013-10-11T14:04:53.420 回答