Ruby 计算可枚举循环上的迭代次数

Ruby 计算可枚举循环上的迭代次数,ruby,enumerator,Ruby,Enumerator,我想使用像[1,2,3]这样的枚举器。循环并计算迭代次数[1,2,3]。cycle.count创建一个无限循环,不会带来迭代计数。我在玩纸牌游戏,它在玩家之间循环。在游戏中很容易说: @round = 0 if @turn == 1 @round += 1 end 它是有效的。但我想知道如何更改计数或添加iter,仅针对具有周期的枚举数,如下所示: module Enumerable def cycle super def count puts "Hi"

我想使用像
[1,2,3]这样的枚举器。循环
并计算迭代次数<代码>[1,2,3]。cycle.count
创建一个无限循环,不会带来迭代计数。我在玩纸牌游戏,它在玩家之间循环。在游戏中很容易说:

@round = 0
if @turn == 1
  @round += 1
end
它是有效的。但我想知道如何更改
计数
或添加
iter
,仅针对具有
周期
的枚举数,如下所示:

module Enumerable
  def cycle  
    super
    def count
      puts "Hi"
    end  
  end  
end  
由于Ruby中的所有内容都是对象,因此我应该能够在函数中创建函数,如下所示:

def x
  def y
    puts 1
  end
end
x.y
# => 1

如何仅在
周期
枚举器内覆盖
计数
的行为,或者至少在
周期
枚举器内创建一个工作方法
iter

您可以相当容易地将类似的内容组合在一起。差不多

class Iter < Array
  attr_reader :iteration

  def initialize(*args)
    super(*args)
    @pointer = 0
    @iteration = 1 # Current iteration
  end

  def next
    self[@pointer].tap {
      @pointer = (@pointer + 1) % size
      @iteration += 1 if @pointer == 0
    }
  end
end

iter = Iter.new [1,2,3]

7.times { puts 'iteration %d: %d' % [iter.iteration, iter.next] }

# iteration 1: 1
# iteration 1: 2
# iteration 1: 3
# iteration 2: 1
# iteration 2: 2
# iteration 2: 3
# iteration 3: 1    
class-Iter
另一个选项,不需要记录下一个呼叫的次数:

class CycledArray
  def initialize(arr)
    @cycle = arr.cycle.each_with_index
    @iteration_length = arr.length
  end

  def next
    @cycle.next.first
  end

  def iterations
    @cycle.peek.last/@iteration_length
  end
end

arr = CycledArray.new([1,2,3])
56.times { arr.next }
arr.next
# => 3
arr.iterations
# => 19
这应该起作用:

ary = [1,2,3]

ary.cycle.with_index do |n,i|
  iteration_number = i / ary.size
  puts "n: #{n} iteration: #{iteration_number}"
  break if i == 10
end

有这么多方法可以做到这一点,嗯?您还可以子类化
数组
,创建枚举器
arr.cycle
,并使用以下命令逐步执行它:

类循环耳环
上面的一些答案在返回迭代/循环计数的方式中包含隐藏的问题;例如,如果在检查迭代之前请求数据,则迭代/计数循环可能是错误的。更有用的方法是返回
[object,iteration]
(类似于
\each_with_index
返回
[object,index]
)并占用一个块

根据@Ursus和@7stud提出的类似问题,我喜欢这个解决方案:

module Enumerable
  def each_with_iteration
    Enumerator.new do |y|
      iteration = 1
      enum = self.cycle
      loop do
        enum.peek # raises StopIteration if self.empty?
        self.size.times do
          e = [enum.next, iteration]
          y << (block_given? ? yield(e) : e)
        end
        iteration += 1
      end
    end
  end
end
用积木:

>> animals = %w(dog duck sheep rabbit)
=> ["dog", "duck", "sheep", "rabbit"]
>> enum = animals.each_with_iteration { |animal, iter| "This is #{animal} number #{iter}" }
=> #<Enumerator: ...>
>> enum.first(7)
=> ["This is dog number 1",
 "This is duck number 1",
 "This is sheep number 1",
 "This is rabbit number 1",
 "This is dog number 2",
 "This is duck number 2",
 "This is sheep number 2"]
>动物=%w(狗鸭羊兔)
=>[“狗”、“鸭”、“羊”、“兔”]
>>enum=animals.each_与_迭代{animal,iter}“这是{animal}编号{iter}”
=> #
>>枚举第一(7)
=>[“这是一号狗”,
“这是鸭子1号”,
“这是一号羊”,
“这是兔子1号”,
“这是2号狗”,
“这是鸭子2号”,
“这是绵羊2号”]
这同样适用于散列、集合、范围或其他可枚举项

编辑:

  • 如果self.empty,添加了一个保护以防止进入无限循环

  • 合并
    产量
    对区块进行操作


  • 这很有效。在这个例子中,我看到迭代开始于
    0
    。@6ftDan-我想这是一个品味问题,在进行完整的迭代之前,我会说
    迭代
    应该是
    0
    …你的迭代不算整个周期的迭代。但是它会计算它在数组中递增的次数。试试这个
    [1,2,3]。cycle.with_index{n,i | break if i==6;puts“VAL:”+String(n)+“ITER:“+String(i)}
    它只计算1-0,2-1,3-2,1-3,2-4,3-5
    CycleArr cycle#cycle_count无法按预期工作
    7.times{p[c.next,c.cycle\u count]}
    返回
    [“dog”,0][“cat”,0][“pig”,1][“dog”,1][“cat”,1][“pig”,2][“dog”,2][code>@moveson,谢谢。奇怪的是,以前没有人注意到这一点。这只是时间问题。如果执行
    [c.cycle\u count,c.next]
    则会得到预期的结果。这仅在调用
    Iter#iteration
    之前调用
    Iter#next
    时有效。返回
    [self.next,iteration]
    的方法
    #next_和_迭代
    将产生意外的结果。我建议添加
    def next_和_迭代;温度=@迭代;[self.next,temp];结束
    >> enum = %w(dog duck sheep rabbit).each_with_iteration
    => #<Enumerator: ...>
    >> 7.times { p enum.next }
    ["dog", 1]
    ["duck", 1]
    ["sheep", 1]
    ["rabbit", 1]
    ["dog", 2]
    ["duck", 2]
    ["sheep", 2]
    => 7
    >> enum.first(7)
    => [["dog", 1],
     ["duck", 1],
     ["sheep", 1],
     ["rabbit", 1],
     ["dog", 2],
     ["duck", 2],
     ["sheep", 2]]
    
    >> animals = %w(dog duck sheep rabbit)
    => ["dog", "duck", "sheep", "rabbit"]
    >> enum = animals.each_with_iteration { |animal, iter| "This is #{animal} number #{iter}" }
    => #<Enumerator: ...>
    >> enum.first(7)
    => ["This is dog number 1",
     "This is duck number 1",
     "This is sheep number 1",
     "This is rabbit number 1",
     "This is dog number 2",
     "This is duck number 2",
     "This is sheep number 2"]