map#
Εφαρμόζει ένα μπλοκ ή μια έκφραση σε κάθε στοιχείο μιας λίστας και επιστρέφει τα ισοπεδωμένα αποτελέσματα.
Η map αποτιμά το BLOCK (ή την EXPR) μία φορά ανά στοιχείο της LIST, με το $_ ψευδωνυμοποιημένο προς εκείνο το στοιχείο, και συλλέγει ό,τι επιστρέφει κάθε αποτίμηση σε μία μοναδική επίπεδη λίστα. Επειδή κάθε αποτίμηση μπορεί να αποδώσει μηδέν, μία ή πολλές τιμές, το μήκος της εξόδου είναι ανεξάρτητο από το μήκος της εισόδου - αυτή η ισοπέδωση είναι το νόημα της map. Σε περιβάλλον λίστας η map επιστρέφει τη γενόμενη λίστα· σε βαθμωτό περιβάλλον επιστρέφει τη συνολική καταμέτρηση στοιχείων.
Σύνοψη#
my @out = map { BLOCK } LIST; # block form
my @out = map EXPR, LIST; # expression form
my @out = map { f($_) } grep { ... } sort LIST; # chained
Τι επιστρέφεται#
Μία μοναδική επίπεδη λίστα που κατασκευάζεται με συνένωση των τιμών επιστροφής κάθε αποτίμησης, στη σειρά εισόδου:
Επιστροφή μίας τιμής ανά είσοδο → μετασχηματισμός (ίδιο μήκος εξόδου).
Επιστροφή λίστας ανά είσοδο → επέκταση 1-προς-N (μεγαλύτερη έξοδος).
Επιστροφή της κενής λίστας
()→ παράλειψη αυτής της εισόδου (μικρότερη έξοδος· ιδίωμαmap-ως-φίλτρο).
Σε βαθμωτό περιβάλλον η τιμή επιστροφής είναι ο αριθμός των γενόμενων στοιχείων, όχι αναφορά και όχι λογική τιμή. Η εκχώρηση του αποτελέσματος σε κατακερματισμό είναι καλά ορισμένη: η επίπεδη λίστα καταναλώνεται ως εναλλασσόμενα ζεύγη κλειδιού/τιμής.
my @doubled = map { $_ * 2 } 1 .. 4; # (2, 4, 6, 8)
my @words = map { split /\s+/, $_ } @lines; # 1-to-N
my @kept = map { $_ > 0 ? $_ : () } @nums; # filter
my $count = map { $_ * $_ } @nums; # scalar ctx
Καθολική κατάσταση#
Το $_ ψευδωνυμοποιείται προς κάθε στοιχείο της LIST, δεν αντιγράφεται. Η τροποποίηση του $_ μέσα στο μπλοκ τροποποιεί το πηγαίο στοιχείο. Αυτό είναι περιστασιακά χρήσιμο αλλά συνήθως παγίδα - επιλέξτε έναν απλό βρόχο foreach όταν εννοείτε επιτόπια τροποποίηση.
my @v = (1, 2, 3);
my @r = map { $_ *= 10; $_ } @v;
# @v is now (10, 20, 30) - the source was mutated
Η ψευδωνυμοποίηση προς μη μεταβλητή (κυριολεκτικό, τιμή επιστροφής συνάρτησης, στοιχείο τομής κατακερματισμού που δεν υπάρχει ακόμη) και έπειτα εκχώρηση στο $_ αποτυγχάνει κατά τον χρόνο εκτέλεσης με Modification of a read-only value. Δείτε το $_.
Η map επίσης τοπικοποιεί το $_ γύρω από την κλήση, οπότε ένα εξωτερικό $_ ορατό στον καλούντα αποκαθίσταται όταν η map επιστρέψει.
Παραδείγματα#
Μετασχηματισμός - μετατροπή κάθε λέξης σε κεφαλαία:
my @upper = map { uc } @words;
Επέκταση 1-προς-N - διαχωρισμός κάθε γραμμής στους λευκούς χαρακτήρες στα tokens της:
my @tokens = map { split /\s+/ } @lines;
Ιδίωμα φίλτρου - διατηρήστε μόνο τις αληθείς, μετασχηματισμένες τιμές:
my @positives = map { $_ > 0 ? $_ : () } @numbers;
Κατασκευή κατακερματισμού από λίστα - κάθε αποτίμηση επιστρέφει λίστα δύο στοιχείων:
my %seen = map { $_ => 1 } @keys;
my %idx = map { ($keys[$_] => $_) } 0 .. $#keys;
Συντεθειμένη διοχέτευση - ταξινόμηση, φιλτράρισμα, μετασχηματισμός. Οι map, grep και sort δέχονται όλες μια LIST στα δεξιά, οπότε αλυσιδώνονται από δεξιά προς τα αριστερά:
my @top = map { "$_->{name}: $_->{score}" }
sort { $b->{score} <=> $a->{score} }
grep { $_->{score} >= 50 }
@records;
Ισοπέδωση δομής - κάθε είσοδος συνεισφέρει μεταβλητό αριθμό εξόδων:
my @leaves = map { ref($_) eq 'ARRAY' ? @$_ : $_ } @mixed;
Ζευγαρώστε με δείκτη χρησιμοποιώντας το List::Util::pairs ή ρητή μεταβλητή δείκτη - η ίδια η map δεν εκθέτει τέτοια:
my @numbered = do {
my $i = 0;
map { sprintf "%d. %s", ++$i, $_ } @items;
};
Οριακές περιπτώσεις#
Το
$_ψευδωνυμοποιείται, δεν αντιγράφεται. Η εκχώρηση στο$_γράφει πίσω στην πηγή. Αν το πηγαίο στοιχείο είναι μόνο για ανάγνωση (σταθερά, τιμή επιστροφής κλήσης συνάρτησης ισοπεδωμένη στηLIST), η εκχώρηση εγείρειModification of a read-only value. Αντιμετωπίστε το$_ως μόνο εισόδου εκτός αν θέλετε συγκεκριμένα την παρενέργεια.Η
mapδεν είναι βρόχος. Οιlast,next,redoκαι οι ετικέτες βρόχου δεν εφαρμόζονται στηmap. Αναφέρονται στον περικλείοντα πραγματικό βρόχο και θα συμπεριφερθούν αναλόγως - συνήθως όχι αυτό που εννοούσε ο συγγραφέας. Χρησιμοποιήστεforeachόταν χρειάζεστε ροή ελέγχου βρόχου.Το κενό περιβάλλον είναι παρωχημένο. Η
map { ... } LIST;με απορριμμένο αποτέλεσμα εκπέμπει προειδοποίησηUseless use of map in void contextυπόuse warnings. Όταν θέλετε τις παρενέργειες, όχι τη λίστα, γράψτεforeach.Αμφισημία αναλυτή
BLOCKέναντιEXPR. Το{εκκινεί τόσο μπλοκ όσο και κατασκευαστή αναφοράς κατακερματισμού. Ταmap { ... } LISTκαιmap { ... }, LISTφαίνονται πανομοιότυπα στον αναλυτή στην ανοιγόμενη αγκύλη· η Perl μαντεύει βάσει του τι ακολουθεί. Ένα μπλοκ που ξεκινά με κάτι που μοιάζει με κλειδί κατακερματισμού συν=>είναι ιδιαίτερα πιθανό να εικαστεί λάθος:my %h = map { "\L$_" => 1 } @a; # guessed EXPR, wrong my %h = map { +"\L$_" => 1 } @a; # unary + forces BLOCK my %h = map {; "\L$_" => 1 } @a; # leading ; forces BLOCK my %h = map { ($_, 1) } @a; # parens - unambiguous my %h = map { lc($_) => 1 } @a; # function call - unambiguous
Για να επιστρέψετε ανώνυμο κατακερματισμό ανά στοιχείο, εξαναγκάστε τον κατασκευαστή αναφοράς κατακερματισμού με
+{:my @hashes = map +{ lc($_) => 1 }, @array;
Η σειρά είναι σταθερή. Η
mapαποτιμά από αριστερά προς τα δεξιά και συνενώνει αποτελέσματα από αριστερά προς τα δεξιά. Η γενόμενη λίστα διατηρεί τη σειρά εισόδου, με τη συνεισφορά κάθε εισόδου να εμφανίζεται συνεχόμενα.Κενή
LIST. Ηmapαποτιμά το μπλοκ μηδέν φορές και επιστρέφει την κενή λίστα. Το μπλοκ δεν αποτιμάται για τις παρενέργειές του.Εμφωλευμένη
map. Η εσωτερικήmapβλέπει το δικό της$_· το εξωτερικό$_επικαλύπτεται για όλη τη διάρκεια της εσωτερικής αποτίμησης. Αποτυπώστε πρώτα την εξωτερική τιμή αν χρειάζονται και οι δύο:my @pairs = map { my $outer = $_; map { [$outer, $_] } @inner } @outer;
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
grep- ίδιου σχήματος με τηmap, αλλά διατηρεί στοιχεία για τα οποία το μπλοκ είναι αληθές αντί να τα μετασχηματίζει· αλυσιδώνεται φυσικά μεmapκαιsortsort- διατάσσει μια λίστα· συνήθως συντίθεται μεmapμέσω του Schwartzian Transform (map→sort→map)for/foreach- χρησιμοποιήστε όταν θέλετε επανάληψη για παρενέργειες, τροποποίηση της πηγής, ή έλεγχο βρόχου (last/next/redo)x- τελεστής επανάληψης λίστας· ορθογώνιος με τηmapαλλά χρησιμοποιείται συχνά για να κατασκευάσει τηLISTπου καταναλώνει ηmapList::Util::reduce- αναδιπλώστε μια λίστα σε μία τιμή· χρησιμοποιήστε όταν το αποτέλεσμα δεν είναι λίστα αλλά συγκεντρωτική τιμή (άθροισμα, μέγιστο, πρώτο ταίριασμα)$_- το ψευδώνυμο στοιχείου μέσα στο μπλοκ· μόνο για ανάγνωση όταν το πηγαίο στοιχείο είναι κυριολεκτικό ή τιμή επιστροφής συνάρτησης