Najlepszy sposób na iterację poprzez tablicę Perla
Jaka jest najlepsza implementacja (pod względem szybkości i wykorzystania pamięci) do iteracji poprzez tablicę Perla? Jest jakiś lepszy sposób? ({[5] } nie muszą być zachowane).
Implementacja 1
foreach (@Array)
{
SubRoutine($_);
}
Implementacja 2
while($Element=shift(@Array))
{
SubRoutine($Element);
}
Implementacja 3
while(scalar(@Array) !=0)
{
$Element=shift(@Array);
SubRoutine($Element);
}
Implementacja 4
for my $i (0 .. $#Array)
{
SubRoutine($Array[$i]);
}
Implementacja 5
map { SubRoutine($_) } @Array ;
6 answers
-
Pod względem szybkości :# 1 i # 4, ale w większości przypadków niewiele.
Możesz napisać benchmark, aby potwierdzić, ale podejrzewam, że #1 i #4 będą nieco szybsze, ponieważ iteracja jest wykonywana w C zamiast w Perlu i nie ma potrzeby kopiowania elementów tablicy. (
$_
jest aliasowane do elementu w #1, ale #2 i #3 faktycznie kopiują Skalary z tablicy.)#5 może być podobne.
-
W kategoriach wykorzystanie pamięci: Wszystkie są takie same, z wyjątkiem # 5.
for (@a)
jest specjalnie obudowany, aby uniknąć spłaszczenia tablicy. Pętla jest powtarzana nad indeksami tablicy. Pod względem czytelności: #1.
-
Pod względem elastyczności: #1 / # 4 i # 5.
#2 nie obsługuje elementów, które są fałszywe. #2 i # 3 są destrukcyjne.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-14 12:22:47
Jeśli zależy Ci tylko na elementach @Array
, Użyj:
for my $el (@Array) {
# ...
}
Lub
Jeśli wskaźniki mają znaczenie, użyj:
for my $i (0 .. $#Array) {
# ...
}
Lub od perl
5.12.1, możesz użyć:
while (my ($i, $el) = each @Array) {
# ...
}
Jeśli potrzebujesz zarówno elementu, jak i jego indeksu w ciele pętli, spodziewałbym się używając each
aby być najszybszym, ale wtedy zrezygnujesz z kompatybilności z pre-5.12.1 perl
s.
Inny wzór niż te może być odpowiedni w pewnych okolicznościach.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-08 03:49:00
IMO, implementacja #1 jest typowa i jest krótka i idiomatyczna dla Perla przebija innych tylko za to. Porównanie tych trzech opcji może dać ci przynajmniej wgląd w szybkość.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-07 19:03:48
1 zasadniczo różni się od 2 i 3, ponieważ pozostawia tablicę w takcie, podczas gdy pozostałe dwie pozostawiają ją pustą.
Powiedziałbym, że #3 jest dość zwariowany i prawdopodobnie mniej wydajny, więc zapomnij o tym.
Co pozostawia cię z #1 i # 2, i nie robią tego samego, więc jeden nie może być "lepszy" od drugiego. Jeśli tablica jest duża i nie musisz jej trzymać, ogólnie scope poradzi sobie z nią (ale zobacz uwaga), więc ogólnie , #1 jest nadal najczystsza i najprostsza metoda. Przesunięcie każdego elementu nie przyspieszy niczego. Nawet jeśli istnieje potrzeba uwolnienia tablicy z referencji, po prostu pójdę:
undef @Array;
Kiedy skończymy.
- uwaga : podprogram zawierający zakres tablicy faktycznie zachowuje tablicę i ponownie używa przestrzeni następnym razem. ogólnie , powinno być dobrze (patrz komentarze).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-07 20:33:24
W jednym wierszu, aby wydrukować element lub tablicę.
Print $ _ for (@array);
Notatka: pamiętaj, że $_ wewnętrznie odnosi się do elementu @array w pętli. Wszelkie zmiany wprowadzone w $_ będą odzwierciedlać w @ array; ex.
my @array = qw( 1 2 3 );
for (@array) {
$_ = $_ *2 ;
}
print "@array";
Wyjście: 2 4 6
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-30 09:09:59
Najlepszy sposób decydowania o takich pytaniach, aby je porównać:
use strict;
use warnings;
use Benchmark qw(:all);
our @input_array = (0..1000);
my $a = sub {
my @array = @{[ @input_array ]};
my $index = 0;
foreach my $element (@array) {
die unless $index == $element;
$index++;
}
};
my $b = sub {
my @array = @{[ @input_array ]};
my $index = 0;
while (defined(my $element = shift @array)) {
die unless $index == $element;
$index++;
}
};
my $c = sub {
my @array = @{[ @input_array ]};
my $index = 0;
while (scalar(@array) !=0) {
my $element = shift(@array);
die unless $index == $element;
$index++;
}
};
my $d = sub {
my @array = @{[ @input_array ]};
foreach my $index (0.. $#array) {
my $element = $array[$index];
die unless $index == $element;
}
};
my $e = sub {
my @array = @{[ @input_array ]};
for (my $index = 0; $index < $#array; $index++) {
my $element = $array[$index];
die unless $index == $element;
}
};
my $f = sub {
my @array = @{[ @input_array ]};
while (my ($index, $element) = each @array) {
die unless $index == $element;
}
};
my $count;
timethese($count, {
'1' => $a,
'2' => $b,
'3' => $c,
'4' => $d,
'5' => $e,
'6' => $f,
});
I uruchamianie tego na perlu 5, wersji 24, subversion 1 (v5.24.1) zbudowanym dla x86_64-linux-gnu-thread-multi
Dostaję:
Benchmark: running 1, 2, 3, 4, 5, 6 for at least 3 CPU seconds...
1: 3 wallclock secs ( 3.16 usr + 0.00 sys = 3.16 CPU) @ 12560.13/s (n=39690)
2: 3 wallclock secs ( 3.18 usr + 0.00 sys = 3.18 CPU) @ 7828.30/s (n=24894)
3: 3 wallclock secs ( 3.23 usr + 0.00 sys = 3.23 CPU) @ 6763.47/s (n=21846)
4: 4 wallclock secs ( 3.15 usr + 0.00 sys = 3.15 CPU) @ 9596.83/s (n=30230)
5: 4 wallclock secs ( 3.20 usr + 0.00 sys = 3.20 CPU) @ 6826.88/s (n=21846)
6: 3 wallclock secs ( 3.12 usr + 0.00 sys = 3.12 CPU) @ 5653.53/s (n=17639)
Więc 'foreach (@Array)' jest około dwa razy szybszy od pozostałych. Wszystkie inne są bardzo podobne.
@ikegami zwraca również uwagę, że istnieje sporo różnic w tych parametrach innych niż prędkość.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-01 11:53:58