Πίνακες#
Ένας πίνακας είναι μια διατεταγμένη, αριθμημένη με ακεραίους ακολουθία βαθμωτών. Το sigil είναι @ για ολόκληρο τον πίνακα και για τομές (που είναι λίστες)· $ για ένα μεμονωμένο στοιχείο (που είναι ένα βαθμωτό). Το αρχικό sigil δηλώνει τον τύπο αποτελέσματος, όχι τον περιέκτη.
my @days = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri');
@days # the whole array (5 elements)
$days[0] # the first element - a single scalar
@days[1, 3] # a slice - a list of two scalars
$#days # the last valid index - here, 4
scalar @days # the length - here, 5
Οι δείκτες ξεκινούν από 0. Οι αρνητικοί δείκτες μετρούν από το τέλος ($days[-1] είναι 'Fri').
Μήκος: $#arr έναντι scalar @arr#
Δύο σχετικά μεγέθη, που χρησιμοποιούνται για διαφορετικούς σκοπούς:
$#days # last valid index - 4
scalar @days # number of elements - 5
$#days + 1 # equivalent to scalar @days
Η ανάθεση στο $#arr αλλάζει το μέγεθος του πίνακα. Η συρρίκνωση καταστρέφει τα στοιχεία πέρα από το νέο τέλος· η αύξηση τα γεμίζει με undef:
my @a = (1, 2, 3, 4, 5);
$#a = 2; # @a is now (1, 2, 3) - length 3
$#a = 5; # @a is now (1, 2, 3, undef, undef, undef)
$#a = -1; # @a is now () - empty
Η μορφή @a = () είναι η ιδιωματική ανάθεση κενού πίνακα· η $#a = -1 είναι ισοδύναμη και μερικές φορές πιο σαφής όταν η πρόθεση είναι «συρρίκνωση στο τίποτα χωρίς αλλαγή ταυτότητας της μεταβλητής».
Πρόσβαση στοιχείων#
my $first = $days[0]; # 'Mon'
my $last = $days[-1]; # 'Fri'
my $last = $days[$#days]; # same; redundant but explicit
$days[2] = 'Wednesday'; # set
$days[10] = 'Sunday'; # auto-extends; $days[5..9] become undef
Η ανάγνωση πέρα από το τέλος επιστρέφει undef (χωρίς προειδοποίηση - η ανάγνωση εκτός εύρους δεν είναι γεγονός). Η εγγραφή πέρα από το τέλος αυξάνει τον πίνακα· οι ενδιάμεσες θέσεις γίνονται undef.
my @a;
$a[5] = 'fifth';
# @a is now (undef, undef, undef, undef, undef, 'fifth')
print scalar @a; # 6
Η ανάγνωση αρνητικού δείκτη πιο πίσω από την αρχή είναι μοιραίο σφάλμα:
my @a = (1, 2, 3);
$a[-10]; # FATAL: Modification of non-creatable
# array value attempted
Λειτουργίες σε ολόκληρο τον πίνακα#
push @arr, $value; # append at end - returns new length
my $v = pop @arr; # remove from end - returns removed element
my $v = shift @arr; # remove from start - returns removed element
unshift @arr, $value; # prepend - returns new length
splice @arr, $offset, $len, @replacement; # general remove/insert
Οι shift και unshift είναι O(n) επειδή αναριθμούν κάθε εναπομείνον στοιχείο· οι push και pop είναι O(1) αποσβεσμένα. Για φόρτους εργασίας τύπου ουράς όπου αυτό έχει σημασία, προτιμήστε push/shift στο σύντομο άκρο ή χρησιμοποιήστε deque από τη List::Util (η οποία έχει αναγωγές, όχι deque).
Η splice είναι ο ελβετικός σουγιάς: αφαιρεί ένα τμήμα στοιχείων, εισάγει ένα τμήμα στη θέση τους, επιστρέφει αυτά που αφαιρέθηκαν:
my @arr = (1, 2, 3, 4, 5);
my @gone = splice @arr, 1, 2; # @gone = (2, 3); @arr = (1, 4, 5)
splice @arr, 1, 0, ('a', 'b'); # insert at offset 1, no removal
# @arr = (1, 'a', 'b', 4, 5)
Αρνητικό $offset μετράει από το τέλος. Αρνητικό $len διατηρεί τόσα τελευταία στοιχεία:
splice @arr, -1; # remove just the last element
splice @arr, 0, -2; # remove all but the last two
Τομές#
Μια τομή εξάγει (ή αναθέτει σε) πολλαπλά στοιχεία ταυτόχρονα. Οι δείκτες προέρχονται από μια λίστα:
my @arr = ('a', 'b', 'c', 'd', 'e');
my @subset = @arr[0, 2, 4]; # ('a', 'c', 'e')
my @middle = @arr[1..3]; # ('b', 'c', 'd')
my @last3 = @arr[-3..-1]; # ('c', 'd', 'e')
my @rev = @arr[reverse 0..$#arr]; # ('e', 'd', 'c', 'b', 'a')
@arr[1, 3] = ('B', 'D'); # set positions 1 and 3
@arr[1, 3] = @arr[3, 1]; # swap two elements (no temp)
Μια τομή κλειδιού/τιμής με % επιστρέφει ζεύγη δείκτη/τιμής (Perl 5.20+):
my @arr = ('a', 'b', 'c', 'd', 'e');
my %picked = %arr[1, 3]; # (1 => 'b', 3 => 'd')
Αυτή είναι η σωστή μορφή όταν χρειάζεστε τόσο τον δείκτη όσο και την τιμή επιλεγμένων στοιχείων. Δείτε subscript για τον πίνακα δώδεκα μορφών τομής.
Περιβάλλον λίστας έναντι βαθμωτού περιβάλλοντος#
Ένας πίνακας σε περιβάλλον λίστας δίνει τα στοιχεία του· σε βαθμωτό περιβάλλον, δίνει το μήκος του:
my @arr = (10, 20, 30);
my @copy = @arr; # list context - three elements
my $length = @arr; # scalar context - 3
print "got @arr\n"; # list context inside "" - "got 10 20 30"
print "got " . @arr . "\n"; # scalar context (concat) - "got 3"
Η διάκριση είναι η πιο συνηθισμένη παγίδα στην Perl. Δύο πρακτικοί κανόνες:
Μέσα σε συμβολοσειρές με διπλά εισαγωγικά, οι πίνακες παρεμβάλλονται ως τα στοιχεία τους ενωμένα με
$"(ένα κενό από προεπιλογή). Δείτε interpolation.Σε περιβάλλον αριθμητικού ή συμβολοσειριακού τελεστή (
+,., σύγκριση), ένας πίνακας δίνει το μήκος του.
Επιβάλετε βαθμωτό περιβάλλον με scalar όταν η θέση της έκφρασης είναι κατά τα άλλα αμφίσημη:
print "got " . scalar(@arr) . " items\n"; # "got 3 items"
print "got @arr items\n"; # "got 10 20 30 items" - different!
Ανάθεση λίστας και το ιδίωμα μέτρησης#
Η ανάθεση μιας λίστας σε έναν πίνακα κάνει τον πίνακα ακριβώς τόσο μεγάλο:
my @arr = (1, 2, 3);
@arr = (10, 20); # @arr is now (10, 20)
@arr = (); # @arr is now empty
Η ανάθεση λίστας σε μια λίστα βαθμωτών αποσυσκευάζει (τα περισσευούμενα απορρίπτονται· τα ελλείποντα γίνονται undef):
my ($x, $y, $z) = (1, 2, 3); # 1, 2, 3
my ($x, $y, $z) = (1, 2); # 1, 2, undef
my ($x, $y) = (1, 2, 3); # 1, 2 - '3' silently dropped
Μια ανάθεση λίστας σε βαθμωτό περιβάλλον επιστρέφει τον αριθμό στοιχείων στη δεξιά πλευρά. Αυτή είναι η πηγή του ιδιώματος μέτρησης:
my $count = () = $string =~ /\d+/g;
# $string =~ /\d+/g - match in list context, returns all matches
# () = LIST - list assignment to empty list
# $count = SCALAR - that assignment in scalar context = count of RHS
Το () = LIST στη μέση είναι το τέχνασμα. Χωρίς αυτό, η $count = $s =~ /\d+/g δίνει λογική τιμή αντί για πλήθος.
Αναφορές πίνακα#
Οι πίνακες δεν είναι τιμές πρώτης τάξης υπό την έννοια ότι μπορούν να μεταβιβαστούν κατ” όνομα μέσα από μια αλυσίδα κλήσεων συναρτήσεων χωρίς ισοπέδωση σε λίστα. Για να μεταβιβάσετε έναν πίνακα χωρίς ισοπέδωση, πάρτε μια αναφορά σε αυτόν:
my @items = (1, 2, 3);
my $aref = \@items; # reference to the existing @items
my $anon = [1, 2, 3]; # anonymous array reference
$aref->[0] # access through the arrow - 1
@{$aref} # fully bracketed deref - list (1, 2, 3)
@$aref # unbracketed deref - same as above
$#{$aref} # last index of dereffed array
scalar @$aref # length
Δείτε references για την πλήρη εικόνα.
Πραγματικό παράδειγμα: κατασκευή ιστογράμματος μηκών λέξεων#
my @words = qw(the quick brown fox jumps over the lazy dog);
my @hist;
$hist[length $_]++ for @words;
for my $len (1 .. $#hist) {
next unless $hist[$len];
printf "%2d-letter words: %d\n", $len, $hist[$len];
}
# 3-letter words: 4
# 4-letter words: 2
# 5-letter words: 3
Σημειώστε ότι η $hist[length $_]++ αυτο-δημιουργεί τη θέση όταν πρόκειται για την πρώτη λέξη αυτού του μήκους. Η ανάγνωση από $hist[7] αργότερα επιστρέφει undef, την οποία η ++ αυξάνει χωρίς πρόβλημα - αλλά η next unless $hist[$len] παραλείπει το κενό πριν την εκτύπωση.
Δείτε επίσης#
Hashes - όταν ο δείκτης είναι συμβολοσειρά, όχι ακέραιος.
References - μεταβίβαση πινάκων χωρίς ισοπέδωση.
Context - η ιστορία λίστας-έναντι-βαθμωτού αναλυτικά.
Interpolation - πώς εμφανίζονται οι πίνακες μέσα σε
"".Subscript and slice operators - η οικογένεια αγκυλών και αγκίστρων αναλυτικά.
Range operator
..- η πιο συνηθισμένη πηγή λιστών δεικτών για τομές.push,pop,shift,unshift,splice- λειτουργίες σε ολόκληρο τον πίνακα.scalar- επιβολή βαθμωτού περιβάλλοντος (μήκος).