2011-07-15 2 views
4

Можно создать дубликат:
What's the difference between iterating over a file with foreach or while in Perl?в то время как против Еогеасп при чтении из STDIN

В цикле в то время, Perl читает строку ввода, помещает его в переменной и управляет телом цикла. Затем он возвращается, чтобы найти еще одну строку ввода . Но в цикле foreach оператор линейного ввода используется в контексте списка (поскольку foreach нуждается в списке для повторения итерации). Поэтому он должен прочитать весь ввод до того, как цикл может начать работать. Эта разница станет очевидной, когда вход поступает из вашего файла журнала веб-сервера 400 МБ! Как правило, лучше всего использовать код, например, ярлык while, который будет обрабатывать ввода строки за раз, когда это возможно. Источник-ламу книга

Так я должен использовать while каждый раз? Каковы возможные ситуации, когда цикл foreach будет доминировать над временем?

+0

Спасибо за ссылку bemace. –

ответ

6

Как вы указываете, итерация по файлу с foreach сбрасывает файл в память до начала цикла.

Хотя это правда, что одно из кредо Перла - «Есть больше, чем один способ сделать это», существуют способы делать вещи, которые не имеют реальной выгоды по сравнению с каким-либо другим способом. foreach, вероятно, является плохой альтернативой для циклического перемещения по файлу. Если вы собираетесь перебирать файл по строкам, вы обычно используете while(). Если вы собираетесь разложить весь файл на память сразу, вы делаете это за один шаг и выполняете его.

Есть иногда преимущества для разграбления всего файла. Например, один из них сводит к минимуму время открытия файла. Чаще всего это удобно для работы с данными, которые по-настоящему не соответствуют строковой записи или записи по модели записи. foreach() удаляет файл, но на самом деле не дает хорошей возможности немедленно его закрыть, так что польза исчезнет.И цикл по файлу с помощью foreach не поможет вам, если ваши данные должны рассматриваться как кусок. Так что причина тоже ушла. В конце концов, вы получаете отрицательный отрыв файла, без каких-либо положительных эффектов для разваливания файла.

Всегда найдется кто-то, кто придумает умную причину, которую другие не рассматривали. Но я еще этого не видел. (Обычно, когда я говорю что-то вроде этого, кто-то пишет «это», поэтому всегда опасно предполагать, что у него нет никаких заслуг.) Скажем так: до тех пор, пока вы не найдете одно из немногих веских оснований для использования foreach для итерации по файл, не беспокойтесь об этом. Конечно, когда вы сделаете это открытие, вы поймете, что пришло время.

+0

Спасибо DavidO :) –

2

Вы используете foreach для перебора каждого элемента массива или каждой клавиши хэша, когда данные уже находятся в памяти. Вы используете while, когда данные еще не хранятся в памяти (и вам может даже не понадобиться хранить все в памяти сразу).

my %hash; 
while (<>) 
{ 
    chomp; 
    my($key, $value) = split /,/; 
    $hash{$key} = $value; 
} 

foreach my $key (sort keys %hash) 
{ 
    print "$key => $hash{$key}\n"; 
} 
5

Общее правило заключается в том, чтобы использовать while если вещь вы работаете с меняется в то время как вы используете его:

while(my $line = <>) 
while(my ($k, $v) = each %h) 

но for или foreach иначе:

foreach my $line (@lines) 
for my $k (keys %h) 
for(my $i = 0; $i < $pancakes; ++$i) 

В случае файла, используя while, имеет смысл, потому что вы (возможно) не хотите, чтобы все это проглотило в память (за исключением, конечно, когда вы этого захотите). Но, если у вас уже есть ваши данные в памяти, тогда for/foreach был бы более естественным выбором для итерации по нему.

Смежные вопросы