環境
- Ruby 2.5.1
実装
進捗を標準出力に表示するEnumerable.each_with_progress
メソッドを、新たに追加します。
index.rb
module Enumerable
def each_with_progress(&block)
self.each_with_index do |element, index|
print "\r#{index + 1}/#{self.length}"
block.call(element, index)
end
print "\r\n"
end
end
print
文を変更すれば、割合表示にしたり色々できると思います。
呼び出し側のコード
index.rb
puts "# program start"
['a','b','c'].each_with_progress do |elem|
sleep 1
print " #{elem}"
end
['a','b','c'].each_with_progress do |elem, index|
sleep 1
print " #{index} -> #{elem}"
end
puts "# program end"
実行結果
$ ruby index.rb
# program start
3/3 c
3/3 2 -> c
# program end
Enumerableで実行可能にする
上記の例は、配列などlength
メソッドが定義されているクラスでしか使えません。
Enumerableでlength
が実装されていないクラス(例えば範囲オブジェクトなど)では、length
の代わりにEnumerable.count
を使います。
index.rb
module Enumerable
def each_with_progress(&block)
length = self.respond_to?(:length) ? self.length : self.count
self.each_with_index do |element, index|
print "\r#{index + 1}/#{length}"
block.call(element, index)
end
print "\r\n"
end
end
こうすることで、Enumerableモジュールを継承しているオブジェクトで実行可能になります。
呼び出し側のコード
index.rb
puts "# program start"
sum = 0
(1..10000).each_with_progress do |elem|
sum += elem
end
puts sum
puts "# program end"
実行結果
$ ruby index.rb
# program start
10000/10000
50005000
# program end