跳过Enumerable#each_cons中的'n'次迭代

时间:2012-07-16 16:38:55

标签: ruby

执行n阻止时是否可以跳过each次迭代?

persons.each_cons(2) do |person|
  if person[0] == person[1]
    #SKIP 2 iterations
  end

  puts "Howdy? #{person[0]}"
end

3 个答案:

答案 0 :(得分:1)

你不能直接这样做。

您可能想要在阵列上拨打uniq,或者如果订单很重要,请查看新的chunk方法:

[1,1,1,2,1,3].uniq # => [1,2,3]
[1,1,1,2,1,3].chunk{|e| e}.map(&:first) # => [1,2,1,3]
# i.e. two adjacent items will always be different

答案 1 :(得分:1)

明确使用Enumerator

persons = [1, 2, 1, 1, 1, 3]
enum = persons.each_cons(2)

loop do
  p1, p2 = enum.next
  if p1 == p2
    2.times { enum.next }
  else
    puts "Howdy? #{p1}"
  end
end

有些说明:

  • 默认情况下,所有循环(例如whileforloop)已经StopIteration抢救break(惊喜),{{ 1}}超级简单
  • 显式使用next就像Ruby一样!获取Ruby Pickaxe书的最近副本,浏览到第4.3章(块和迭代器)并享受!
  • 不要错过平行分配,即使是在块中
  • 如果您无法按照自己想要的方式导航Enumerator,建议您花10分钟阅读模块文档:许多人可以发现Enumerable#each_cons之间的差异具有启发性就像我一样 特别是,至少要检查从#each_slicechunkdropeach开始的所有方法名称(评论中欢迎提供更多建议!) 。手动调用slice实际上很少见。

加分:

了解“迭代器”和#next之间的区别(上面提到的相同的镐章)实际上确实派上用场了。
有时,通过构建自定义迭代器可以更好地解决您的难题:

Enumerator

为什么要了解自定义迭代器?想象一下,你需要操作任意大的(注意persons = [1, 2, 1, 1, 1, 3] custom_iter = Enumerator.new do |yielder| en = persons.each_cons(2) loop do 2.times { en.next } while (p1, p2 = en.next).reduce(:==) yielder.yield p1 end end custom_iter.each { |pers| puts "Howdy? #{pers}" } )组偶数:

#lazy

Ruby公开元素枚举而不是列表迭代的方式可以改变你对序列和集合的思考方式 - 给它一个机会;)

答案 2 :(得分:0)

另一种方法是使用each迭代器,而不是真正的红宝石。

persons = [1,1,2,2,2,3,4,4,5,5,6,7,8,9]

persons_iterator = persons.each
begin
  while first_person = persons_iterator.next do
    second_person = persons_iterator.next
    if first_person == second_person
      persons_iterator.next.next # Skip 2 iterations
    end

    puts "Howdy? #{first_person}"
  end
rescue StopIteration
  # Iterator end
end