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-5CycleArr 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"]