问题
I would like to use an enumerator like [1,2,3].cycle and count how many times I've gone through the iterations. [1,2,3].cycle.count creates an infinite loop and doesn't bring the iteration count. I'm playing a card game, and it cycles through the players. It's easy in the game to say:
@round = 0
if @turn == 1
@round += 1
end
and it works. But I would like to know how to change count or add iter only for enumerators with cycle into something like this:
module Enumerable
def cycle
super
def count
puts "Hi"
end
end
end
Since everything in Ruby is an Object, I should be able to create functions within functions as this case works:
def x
def y
puts 1
end
end
x.y
# => 1
How can I overwrite the behaviour of count only within a cycle enumerator or at least create a working method iter within the cycle Enumerator?
回答1:
You can put something like that together fairly easily. Something like
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
回答2:
Another option, which does not need to keep count of the number of calls to next:
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
回答3:
This should work:
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
回答4:
So many ways to do this, eh? You could also subclass Array, create an enumerator arr.cycle and step through it using Enumerator#next:
class CycleArr < Array
def initialize arr
@sz = arr.size
@enum = arr.cycle
end
def next
@count = (@count ||= 0) + 1
@enum.next
end
def cycle_count
1 + (@count - 1) % @sz
end
end
c = CycleArr.new(['dog', 'cat', 'pig'])
7.times { p [c.next, c.cycle_count] }
# ["dog", 1]
# ["cat", 2]
# ["pig", 3]
# ["dog", 1]
# ["cat", 2]
# ["pig", 3]
# ["dog", 1]
回答5:
Some of the answers above contain hidden problems in the way iteration/cycle_count is returned; for example, the iteration/count_cycle may be wrong if the data is requested before the iteration is checked. A more useful method would return [object, iteration] (analogous to the way #each_with_index returns [object, index]) and would take a block.
Drawing from @Ursus and @7stud based on the similar question I asked here, I like this solution:
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
This makes it a close analog to Enumerable#each_with_index, for example:
>> 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]]
And with a block:
>> 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"]
This also works as expected on a Hash, Set, Range, or other Enumerable.
EDIT:
Added a guard to keep from entering an infinite loop if self.empty?
Incorporated
yieldto operate on a block.
来源:https://stackoverflow.com/questions/24764323/count-iteration-on-the-enumerable-cycle