Я хотел бы написать метод, возвращающий перечислитель (похожий на тот, который возвращается File::foreach
), который возвращает каждую строку файла последовательно, но с перебором. Мой первый подход был
def chomped_lines(filename)
File.foreach(filename).map(&:chomp).each
end
И использовать его как
my_enum = chomped_lines('my_file.txt')
....
my_enum.each { |line| .... }
Думаю, Enumerator :: lazy можно как-то использовать здесь, но в любом случае код должен работать на Ruby 1.9.3, а это значит, что у меня еще нет ленивых счетчиков.
Как лучше написать такой счетчик?
Кажется, это работает, но если я правильно понимаю (поправьте меня, если я ошибаюсь), файл будет помещен в память в целом в память, чтобы применить map
.
2 ответа
Вы можете создать перечислитель следующим образом. Сначала создадим файл для демонстрации.
str =<<_
Now is the
time for all
Rubiests to
come to the
aid of their
bowling team.
_
fname = "temp"
File.write(fname, str)
#=> 75
IO # foreach без блока возвращает перечислитель :
efe = File.foreach(fname)
#=> #<Enumerator: File:foreach("temp")>
Поэтому нам нужно просто встроить этот перечислитель в другой, который перехватывает символ новой строки из строки:
echomp = Enumerator.new do |y|
loop do
y << efe.next.chomp
end
end
#=> #<Enumerator: #<Enumerator::Generator:0x007fbe128837b8>:each>
Давай попробуем:
echomp.next
#=> "Now is the"
echomp.next
#=> "time for all"
echomp.next
#=> "Rubiests to"
echomp.next
#=> "come to the"
echomp.next
#=> "aid of their"
echomp.next
#=> "bowling team."
echomp.next
#=> StopIteration: iteration reached an end
Конечно, вы можете обернуть это методом:
def foreach_with_chomp(fname)
efe = File.foreach(fname)
Enumerator.new do |y|
loop do
y << efe.next.chomp
end
end
end
foreach_with_chomp(fname).each { |s| print "#{s} " }
Now is the time for all Rubiests to come to the aid of their bowling team.
Я написал класс, который, как мне кажется, делает то, что вы хотите. Он также размещен в качестве основной на https://gist.github.com/keithrbennett/9f126fa17d9df5e198ac8ac.
После определения класса есть код, который использует класс несколькими способами.
#!/usr/bin/env ruby
class ChompedFileLines
include Enumerable
def initialize(filespec)
@filespec = filespec
end
def each
File.foreach(@filespec) { |line| yield line.chomp }
end
end
# Exercise the class:
FILESPEC = '/usr/share/dict/words'
chomped_file_lines = ChompedFileLines.new(FILESPEC)
puts; p chomped_file_lines; puts
chomped_file_lines.first(10).each { |line| p line }
chomped_file_lines_enum = ChompedFileLines.new(FILESPEC).to_enum
puts; p chomped_file_lines_enum; puts
10.times { p chomped_file_lines_enum.next }
Похожие вопросы
Новые вопросы
ruby
Ruby - это многоплатформенный динамический объектно-ориентированный интерпретируемый язык с открытым исходным кодом. Тег [ruby] предназначен для вопросов, связанных с языком Ruby, включая его синтаксис и его библиотеки. Вопросы Ruby on Rails должны быть помечены [ruby-on-rails].