2013-09-08 2 views
3

У меня есть следующий код Perl.Я не могу понять следующий код Perl

#!/usr/bin/perl 
use strict; 
use warnings; 
use diagnostics; 

my @array = ( 3, 4, 1, 4, 7, 7, 4, 1, 3, 8); 
my %unordered; 
@unordered{@array} = undef; 

foreach my $key (keys %unordered) { 
print "Unordered: $key\n"; 
} 

my %seen; 
my @ordered; 

foreach my $element (@array) { 
    if ( not $seen{$element}++) { 
    push @ordered, $element; 
    } 
} 

В последнем foreach блоке кода, я не могу понять это - в первой итерации выражение not $seen{$element}++ оценки не 0 - правда - так, если блок выполнения. Во второй итерации выражение not $seen{$element}++ должно снова оценить не 0 - true, поскольку хеш пуст. Итак, чтение скаляра $seen{$element} будет читать 0, а не 0 будет оцениваться как true. Итак, блок if должен выполнить снова. Но в книге говорится, что она прекращается после первой итерации. Может кто-нибудь объяснить это?

+4

Что вы думаете '' ++ делает здесь? –

+3

Хэш '% seen' имеет те же ключи, что и'% unordered', поэтому их можно использовать таким же образом, не создавая два хэша. – Borodin

ответ

2

На второй итерации хеш больше не будет пустым, так как оператор ++ разместит там 1. На третьей итерации значение будет 2 (что для целей этой программы такое же, как 1, это просто означает «видно хотя бы раз раньше»).

В конце вашей программы %seen будет содержать количество раз, когда каждая запись появляется в вашем списке.

if $a++ увеличивает значение $a (обрабатывает его как 0, если отсутствует), а затем возвращает значение до этого приращения к сравнению.

Важно использовать оператор постфикса, а if ++$a не будет работать здесь: Он также размещает в вашей хэш с 1, но он возвращает значение (так 1 даже для первой итерации).

+0

Во второй итерации элемент $ будет иметь значения 2 в строке foreach. Таким образом, $ seen {$ element} снова будет undef, т. Е. 0. И, если блок должен выполнить. –

+0

@ RabinHalder, не верно. Только '++' влияет на содержимое '% seen',' not' - только на пользу 'if'. – tjd

0

В последнем цикле Еогеаспа может быть, как Детальный:

# loop on all elements of the array 
foreach my $element (@array) { 
    # if the current element haven't been seen yet 
    if (not exists $seen{$element}) { 
     # add current element into ordered array 
     push @ordered, $element; 
    } 
    # Increment the number of time element have been seen 
    $seen{$element}++; 
} 

В конце концов, @ordered будет содержать:

(3, 4, 1, 7, 8) 

Лучше имя должно быть @unique вместо @ordered.

%seen будет содержать:

(3 => 2, 4 => 3, 1 => 2, 7 => 2, 8 => 1) 
Смежные вопросы