4

n执行块时是否可以跳过迭代each

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

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

3 回答 3

4

只需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


一些注意事项:

  • 默认情况下,所有循环(例如while, for, )已经通过ing 进行loop救援(惊喜惊喜),使ing 超级容易StopIterationbreaknext
  • 显式使用Enumeratoris 和 Ruby 一样!拿一本最新的 Ruby Pickaxe 书,浏览到第 4.3 章(块和迭代器),尽情享受吧!
  • 不要错过并行分配,即使是在块中
  • 如果您无法按照自己想要的方式进行导航,我建议您花 10 分钟时间阅读模块文档:许多人可以像我一样Enumerable发现两者之间的区别#each_cons和启发性。 特别是,请至少查看所有以 、 和 开头的方法名称(欢迎评论中提出更多建议!)。不得不手动调用实际上很少见。#each_slice
    chunkdropeachslice#next

奖励积分:

了解“迭代器”和(与上面提到的 Pickaxe 相同的章节)之间的区别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)偶数集进行操作:

def Integer.even from:0
  Enumerator.new do |yielder, n: (from.even? ? from : from+1 )|
    loop { yielder.yield n; n += 2}
  end.lazy
end

p Integer.even(from: 3).take(10).to_a

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

于 2016-12-16T14:48:08.620 回答
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
于 2012-07-16T16:49:27.440 回答
0

另一种与 ruby​​ 不同的方法是使用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
于 2012-07-16T18:47:10.053 回答