each#
Διάσχιση ενός πίνακα κατακερματισμού ή πίνακα μία εγγραφή τη φορά.
Η each προωθεί έναν επαναλήπτη ανά container και επιστρέφει την επόμενη εγγραφή. Για έναν πίνακα κατακερματισμού αυτή η εγγραφή είναι ένα ζεύγος (key, value)· για έναν πίνακα είναι ένα ζεύγος (index, value). Όταν ο επαναλήπτης έχει διασχίσει κάθε εγγραφή, η επόμενη κλήση επιστρέφει την κενή λίστα (ή undef σε βαθμωτό περιβάλλον) και έπειτα επανέρχεται στην αρχή, ώστε ένας νέος βρόχος while (each ...) να ξεκινήσει από την αρχή. Η σειρά του πίνακα κατακερματισμού είναι τυχαία ανά διεργασία και ανά πίνακα κατακερματισμού· η σειρά του πίνακα είναι αυστηρά από τον χαμηλότερο δείκτη προς τα πάνω.
Σύνοψη#
while (my ($k, $v) = each %h) { ... }
while (my ($i, $v) = each @a) { ... }
while (each %h) { ... } # sets $_ to the key
my $k = each %h; # scalar context: key/index only
Τι επιστρέφεται#
Περιβάλλον λίστας: μια λίστα δύο στοιχείων
($key, $value)για έναν πίνακα κατακερματισμού,($index, $value)για έναν πίνακα. Σε εξάντληση, η κενή λίστα.Βαθμωτό περιβάλλον: το κλειδί (για πίνακα κατακερματισμού) ή ο δείκτης (για πίνακα). Σε εξάντληση,
undef.Σκέτη
each %hσε συνθήκηwhile/for: ελέγχει την οριστικότητα του επιστρεφόμενου κλειδιού/δείκτη, όχι την αληθοτιμή, και εκχωρεί το κλειδί στην$_. Αυτό κάνει τοwhile (each %h) { print "$_\n" }να λειτουργεί ακόμη και όταν ένα κλειδί είναι η κενή συμβολοσειρά ή0.
Μετά την εξάντληση ο επαναλήπτης επαναφέρεται σιωπηρά, οπότε η κλήση μετά από εκείνη που επέστρεψε κενή ξαναξεκινά την επανάληψη από την αρχή.
Καθολική κατάσταση που επηρεάζει#
Κάθε πίνακας κατακερματισμού και κάθε πίνακας φέρει τον δικό του εσωτερικό επαναλήπτη. Οι each, keys και values προωθούν και μοιράζονται όλες αυτόν τον έναν επαναλήπτη - είναι τρεις όψεις του ίδιου δρομέα, όχι τρεις ανεξάρτητοι βρόχοι. Αυτό είναι το πιο σημαντικό μεμονωμένο γεγονός σχετικά με την each:
Η κλήση
keys %hήvalues %h(σε οποιοδήποτε περιβάλλον, ακόμη και ως εφάπαξ μέτρηση όπωςscalar keys %h) επαναφέρει τον επαναλήπτη του πίνακα κατακερματισμού. Ένας βρόχοςwhile (each %h)που διακόπτεται απόscalar keys %hστο σώμα του θα ξαναξεκινήσει από την αρχή στην επόμενη επανάληψη - ή χειρότερα, θα εκτελείται για πάντα.Η αναφορά ενός πίνακα κατακερματισμού σε περιβάλλον λίστας επαναφέρει επίσης τον επαναλήπτη του (π.χ.
my @copy = %h, ή πέρασμα της%hσε υπορουτίνα). Οι επαναλήπτες πινάκων δεν επαναφέρονται από αναφορά σε περιβάλλον λίστας.Δύο βρόχοι που επαναλαμβάνουν το ίδιο
%hμοιράζονται έναν δρομέα. Η εμφώλευσηwhile (each %h) { ... while (each %h) { ... } ... }επισκέπτεται κάθε εγγραφή το πολύ μία φορά συνολικά, όχιn * mφορές.Ένας ανώνυμος πίνακας κατακερματισμού/πίνακας στη συνθήκη (
each %{ +{ a => 1 } }) κατασκευάζει έναν νέο container σε κάθε επανάληψη, οπότε ο επαναλήπτης είναι πάντα φρέσκος - ο βρόχος δεν τερματίζει ποτέ.Η σκέτη μορφή της
eachεκχωρεί στην$_· αν βασίζεστε στην$_αλλού στο σώμα του βρόχου, αποθηκεύστε την μεlocal.
Κάθε είσοδος σε ένα βρόχο while (each ...) λαμβάνει όποια θέση επαναλήπτη βρίσκεται ο container εκείνη τη στιγμή. Δεν υπάρχει τρόπος να απομονώσετε τον επαναλήπτη ενός βρόχου από άλλο κώδικα που αγγίζει τον ίδιο container. Αν το σώμα του βρόχου καλεί συνάρτηση που μπορεί να διαβάσει τον ίδιο πίνακα κατακερματισμού, το ασφαλές μοτίβο είναι αντί αυτού ένας βρόχος foreach πάνω σε keys.
Παραδείγματα#
Βασική επανάληψη πίνακα κατακερματισμού:
my %colour = (red => "#f00", green => "#0f0", blue => "#00f");
while (my ($name, $hex) = each %colour) {
print "$name = $hex\n";
}
# order is unspecified
Επανάληψη πίνακα (Perl 5.12+):
my @letters = ('a' .. 'e');
while (my ($i, $c) = each @letters) {
print "[$i] $c\n";
}
# [0] a
# [1] b
# [2] c
# [3] d
# [4] e
Εκτύπωση πίνακα κατακερματισμού σε ταξινομημένη σειρά - η each δεν ταξινομεί, οπότε καταφύγετε αντί αυτού σε keys συν sort:
for my $k (sort keys %colour) {
print "$k = $colour{$k}\n";
}
Σκέτη each σε συνθήκη while, που θέτει την $_ στο κλειδί σε κάθε επανάληψη (Perl 5.18+):
while (each %ENV) {
print "$_=$ENV{$_}\n";
}
Ασφαλής διαγραφή κατά την επανάληψη - μπορείτε να διαγράψετε το κλειδί που μόλις επιστράφηκε από την each χωρίς να ενοχλήσετε τον δρομέα:
while (my ($key, $value) = each %hash) {
delete $hash{$key} if $value < 0; # safe
}
Επανάληψη πίνακα κατακερματισμού με βρόχο foreach όταν οτιδήποτε στο σώμα μπορεί να αγγίξει το %hash (το εύρωστο μοτίβο - λάβετε πρώτα στιγμιότυπο των κλειδιών):
for my $key (keys %hash) {
my $value = $hash{$key};
# body is free to read %hash, call subs that read it, even
# mutate it cautiously - our iteration list is fixed already.
}
foreach πολλαπλών τιμών πάνω σε πίνακα κατακερματισμού (Perl 5.36+), που καθιστά την each περιττή για τους περισσότερους βρόχους και αποφεύγει την παγίδα του κοινόχρηστου επαναλήπτη:
foreach my ($key, $value) (%hash) {
print "$key => $value\n";
}
Οριακές περιπτώσεις#
Ο επαναλήπτης δεν επαναφέρεται μεταξύ επανεισόδων: ένας βρόχος
while (each %h)που εξέρχεται πρόωρα μέσωlast,returnήdieαφήνει τον επαναλήπτη στη μέση της διάσχισης. Ο επόμενοςwhile (each %h)στον ίδιο πίνακα κατακερματισμού συνεχίζει από εκεί που σταμάτησε ο πρώτος, όχι από την αρχή. Καλέστεkeys %hσε περιβάλλον κενού -keys %h;- για να εξαναγκάσετε επαναφορά πριν τον νέο βρόχο.Οι
keys/valuesεπαναφέρουν τον επαναλήπτη: οποιαδήποτε κλήση στιςkeysήvaluesστον ίδιο πίνακα κατακερματισμού - συμπεριλαμβανομένης τηςscalar keys %hμέσα στο σώμα του βρόχου - επαναφέρει τον δρομέα.Η αναφορά σε περιβάλλον λίστας επαναφέρει τον επαναλήπτη πίνακα κατακερματισμού, όχι πίνακα: το
my @flat = %hεπαναφέρει τον δρομέα του%h· το ισοδύναμοmy @copy = @aδεν αγγίζει τον επαναλήπτη του@a.Η διαγραφή κατά την επανάληψη δεν είναι καθορισμένη εκτός από την εγγραφή που επιστράφηκε πιο πρόσφατα. Η διαγραφή οποιουδήποτε άλλου κλειδιού μπορεί να οδηγήσει σε εγγραφές που επισκέπτονται δύο φορές ή παραλείπονται εντελώς.
Η προσθήκη κατά την επανάληψη δεν είναι καθορισμένη - η εισαγωγή νέου κλειδιού στη μέση του βρόχου μπορεί να επισκεφθεί ή να μην επισκεφθεί, και μπορεί να διαταράξει τη σειρά των εγγραφών που δεν έχουν ακόμη ιδωθεί.
Ανώνυμος container στη συνθήκη: η
each %{ +{ a => 1 } }ή ηeach @{ [1,2,3] }κατασκευάζει έναν φρέσκο container κάθε φορά που αποτιμάται η συνθήκη, οπότε ο επαναλήπτης είναι πάντα νέος και ο βρόχος δεν τερματίζει ποτέ.Δεσμευμένοι πίνακες κατακερματισμού και πίνακες εκχωρούν στις
FIRSTKEY/NEXTKEY(πίνακες κατακερματισμού) ήFETCHSIZE/FETCH(πίνακες), οπότε η σειρά επανάληψης είναι ό,τι επιλέγει η δεσμευμένη κλάση και καμία από τις παραπάνω εγγυήσεις δεν ισχύει απαραίτητα.Οριστικότητα έναντι αληθοτιμίας στη συνθήκη βρόχου: τα
while (each %h)καιwhile (my $k = each %h)ελέγχουν αμφότερα την οριστικότητα της έκφρασης, οπότε ένα κλειδί"0"ή""δεν τερματίζει τον βρόχο. Αυτό αποτελεί ειδική περίπτωση συγκεκριμένα για τηνeach.Βαθμωτές εκφράσεις: η
each $hrefσε βαθμωτό που κρατά αναφορά ήταν πειραματικό χαρακτηριστικό στην 5.14 και αφαιρέθηκε στην 5.24. Αποαναφέρετε ρητά:each %$href,each @$aref.Κοινόχρηστη κατάσταση μεταξύ υπορουτινών: το πέρασμα του
%hσε υπορουτίνα που καλείeach %h,keys %hήvalues %hπάνω του διαταράσσει τον επαναλήπτη του καλούντος. Αν δημοσιεύετε έναν πίνακα κατακερματισμού, υποθέστε ότι οι καλούντες μπορεί να σπάσουν τον βρόχο σας· προτιμήστεforeach (keys ...)για ευρωστία.
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
keys- στιγμιότυπο όλων των κλειδιών (πίνακας κατακερματισμού) ή δεικτών (πίνακας)· επαναφέρει τον επαναλήπτη που χρησιμοποιεί ηeachvalues- στιγμιότυπο όλων των τιμών· επαναφέρει τον επαναλήπτη που χρησιμοποιεί ηeachdelete- ασφαλής για την εγγραφή που μόλις επιστράφηκε από τηνeach, μη ασφαλής για οποιαδήποτε άλλη κατά την επανάληψηexists- έλεγχος ύπαρξης κλειδιού/δείκτη χωρίς διατάραξη του επαναλήπτηfor/foreach- ο πιο ασφαλής βρόχος όταν το σώμα μπορεί να αγγίξει τον container· συνδυάστε μεkeysγια να λάβετε πρώτα στιγμιότυποsort- συνδυάστε μεkeysόταν χρειάζεστε καθορισμένη σειρά επανάληψης· ηeachδεν ταξινομεί ποτέ