2010-08-23 18 views
7

Chcę tworzyć tablice dynamicznie na podstawie danych wprowadzanych przez użytkownika. Na przykład, jeśli użytkownik poda dane wejściowe jako 3, należy utworzyć trzy tablice o nazwach @message1, @message2 i @message3.Tworzenie tablic dynamicznie w Perlu

Jak zrobić to w Perlu?

+0

szansa na bardzo krótkiej odpowiedzi : [perllol] (http: // perldoc.perl.org/perllol.html). Nawet Perl ma LOLz. – Dummy00001

Odpowiedz

12

Muszę zapytać, dlaczego chcesz to zrobić, ponieważ nie jest to właściwa droga. Jeśli masz trzy strumienie wejścia, z których każda musi być przechowywany w postaci listy, a następnie przechowywać jeden listę, która jest lista list (gdzie wykazy są przechowywane jako odniesień tablicy):

my @input = (
    [ 'data', 'from', 'first', 'user' ], 
    [ qw(data from second user) ], 
    [ qw(etc etc etc) ], 
); 

Jeśli mają nazwy związane z danymi każdego użytkownika, można użyć tego jako klawisz skrótu, dla indeksowania danych przed:

my %input = (
    senthil => [ 'data', 'from', 'first', 'user' ], 
    ether => [ qw(data from second user) ], 
    apu => [ qw(etc etc etc) ], 
); 

Proszę odnieść się do Perl Data Structures Cookbook (perldoc perldsc) dłużej na temat wyboru właściwej struktury danych dla sytuacji i zdefiniowania ich jako .

+4

Dobra odpowiedź - poza kilkoma odsyłaczami do "list", gdy masz na myśli "tablice". W Perlu listy i tablice to nie to samo. Listy są danymi, tablice są zmiennymi. Różnica jest subtelna, ale ważna. –

+0

@davorg: Miałem na myśli listy, kiedy wymawiałem listy. Listy mogą być przechowywane jako * tablice * lub * arrayrefs *, a także w * hashe *. – Ether

+0

nie, niezupełnie. tablice lub skróty mogą tworzyć listy lub być inicjowane z listy, ale nie dokładnie * przechowują * listy. Nadal dałbym "liście zapisane w tablicy" hasło, ale "lista przechowywana * jako * tablica" jest zbyt myląca. – ysth

17

Nie. Zamiast używać tablicy tablic:

my @message; 
my $input = 3; 
for my $index (0..$input-1) { 
    $message[$index][0] = "element 0"; 
    $message[$index][1] = 42; 
} 
print "The second array has ", scalar(@{ $message[1] }), " elements\n"; 
print "They are:\n"; 
for my $index (0..$#{ $message[1] }) { 
    print "\t", $message[1][$index], "\n"; 
} 

Kilka cennych zasady są w http://perlmonks.org/?node=References+quick+reference

2

W zestawionych językach, zmienne nie mają nazwy. Nazwa widoczna w kodzie jest unikalnym identyfikatorem powiązanym z pewnym przesunięciem liczbowym. W identyfikatorze takim jak message_2 służy tylko do tego, aby był unikalnym identyfikatorem. Każdy może powiedzieć, że możesz wykonać trzy zmienne: message_125, message_216 i message_343. Dopóki możesz powiedzieć, co powinieneś umieścić w czym, działają tak dobrze, jak message_1 ...

"Nazwa" zmiennej jest tylko dla Ciebie, zachowując je podczas pisania kodu.

Dynamiczne języki dodają możliwości, nie czyszcząc tabel symboli. Ale tablica symboli to po prostu skojarzenie nazwy z wartością. Ponieważ Perl oferuje tak tanie listy i hashe, nie ma potrzeby używania programowania/logistycznej metody śledzenia zmiennych, aby umożliwić elastyczny dostęp do środowiska wykonawczego.

Są szanse, że jeśli pojawi się nazewnictwa list @message1, @message2 ... - gdzie elementy różnią się tylko ich kolejność odniesienia, że ​​nazwy te są tak samo dobre: ​​$message[1], $message[2], ....

Ponadto, ponieważ tabele symboli zwykle odwzorowują od nazwy do przesunięcia (na stosie lub w stercie), to naprawdę nie jest o wiele więcej niż para klucz-wartość, którą można znaleźć w hash. Tak więc hashe działają tak samo dobrze, jak wyszukiwanie bardziej odrębnych nazw.

$h{messages} = []; 
$h{replies} = []; 

mam na myśli naprawdę, jeśli chcesz, możesz zapisać wszystko, co można umieścić w zmiennej leksykalnej w jeden hash dla zakresu, jeśli nie przeszkadza w piśmie: $h{variable_name} za wszystko. Ale nie uzyskałbyś korzyści z niejawnego zarządzania Perla, a w różnych językach programiści preferowali domyślne zarządzanie zakresem.

Perl umożliwia symboliczną manipulację, ale przez lata języki dynamiczne odkryły mieszane błogosławieństwo. Ale w Perlu masz obie "perspektywy", aby nadać im nazwę. Ponieważ możesz określić, który kod w skompilowanym języku może być lepszy niż język dynamiczny, ustalono, że więcej "bezbłędnie" ma "skompilowaną perspektywę" na więcej rzeczy: tak jak widać z dostępnością zarządzania offsetami i sprawdź kompilowane zachowanie podane tobie w rdzeniu Perla, nie ma powodu, aby zadzierać z tablicą symboli, jeśli nie musisz.

Tworzenie tablicy dynamicznie jest tak proste, jak: []. Przypisując je do miejsca w pamięci, kiedy nie wiemy, ile chcemy przechowywać, jest tak proste, jak:

push @message, []; 

i tworząc listę list wszystkich naraz jest tak proste, jak:

@message = map { [] } 1..$num_lists; 

dla określonej wartości w $num_lists.

+2

'([]) x' tworzy wiele kopii tego samego odwołania do tablicy; chcesz 'map ([], 1 .. $ num_lists) zamiast tego – ysth

+0

@yst, wiesz, napisałem to najpierw z mapą, ale myślałem, że mnożnik wygląda szybciej. :) – Axeman

+0

i tak jest :) – ysth

3

Dynamiczne tworzenie nowych nazwanych tablic prawie nigdy nie jest dobrym pomysłem. Mark Dominus, autor książki oświecającej Higher-Order Perl, napisał szczegółowy opis pułapek.

mieć nazwy w pamięci dla tych tablic, więc umieścić je w hash:

sub create_arrays { 
    my($where,$n) = @_; 

    for (1 .. $n) { 
    $where->{"message$_"} = []; 
    } 
} 

na szybki przykład, który pokazuje strukturę, poniższy kod

my $n = @ARGV ? shift : 3; 

my %hash; 
create_arrays \%hash, $n; 

use Data::Dumper; 
$Data::Dumper::Indent = $Data::Dumper::Terse = 1; 
print Dumper \%hash; 

wyjść

$ ./prog.pl 
{ 
    'message2' => [], 
    'message3' => [], 
    'message1' => [] 
}

Podając inną liczbę tablic, otrzymujemy

$ ./prog.pl 7 
{ 
    'message2' => [], 
    'message6' => [], 
    'message5' => [], 
    'message4' => [], 
    'message3' => [], 
    'message1' => [], 
    'message7' => [] 
}

Kolejność klawiszy wygląda śmiesznie, ponieważ znajdują się w haśle, nieuporządkowanej strukturze danych.

Przypomnijmy, że [] tworzy odniesienie do nowego anonimowej tablicy, tak, na przykład, aby dodać wartości do komunikat2, można by napisać

push @{ $hash{"message2"} }, "Hello!"; 

Aby wydrukować go, można by napisać

print $hash{"message2"}[0], "\n"; 

Może zamiast chcesz wiedzieć, jak długo wszystkie tablice są:

foreach my $i (1 .. $n) { 
    print "message$i: ", scalar @{ $hash{"message$i"} }, "\n"; 
} 

dla m rudy szczegółowe informacje na temat korzystania z odniesień w Perlu, zobacz następujące dokumenty: