Πίνακες

shift#

Αφαιρεί και επιστρέφει το πρώτο στοιχείο ενός πίνακα.

Η shift μεταλλάσσει το όρισμά της: αφαιρεί το στοιχείο στη θέση 0, μετατοπίζει κάθε υπόλοιπο στοιχείο κάτω κατά μία θέση, και επιστρέφει την τιμή που αφαιρέθηκε. Ο πίνακας συρρικνώνεται κατά ένα. Αν ο πίνακας είναι κενός, δεν αφαιρείται τίποτα και επιστρέφεται undef.

Σύνοψη#

shift @arr
shift @$aref
shift                   # @_ inside a sub, @ARGV outside

Τι επιστρέφεται#

Το βαθμωτό που βρισκόταν στη θέση 0, ή undef αν ο πίνακας ήταν κενός. Επειδή το undef είναι επίσης νόμιμο στοιχείο πίνακα, μια σκέτη επιστροφή undef δεν σημαίνει από μόνη της ότι ο πίνακας ήταν κενός - χρησιμοποιήστε scalar @arr ή προηγούμενο έλεγχο defined όταν η διάκριση έχει σημασία:

my @arr  = (undef, 'two');
my $item = shift @arr;      # undef - but @arr was not empty

Προεπιλεγμένος πίνακας: @ARGV έναντι @_#

Όταν καλείται χωρίς όρισμα, η shift επιλέγει τον πίνακά της από το περιβάλλον συγκείμενο:

  • Μέσα σε κατονομασμένη ή ανώνυμη υπορουτίνα - @_. Αυτός είναι ο ιδιωματικός τρόπος για να καταναλώνετε ορίσματα κατά θέση ένα-ένα.

  • Outside any sub (including in the file scope of a script, and in eval STRING, BEGIN, INIT, CHECK, UNITCHECK, END blocks)

    • @ARGV. This is how top-of-script argument consumption is usually written.

Η επιλογή γίνεται κατά τη μεταγλώττιση βάσει της λεξιλογικής θέσης, όχι κατά τον χρόνο εκτέλεσης. Μια shift μέσα σε sub στοχεύει πάντα το @_ ακόμα κι αν η sub καλείται από εμβέλεια αρχείου.

Παραδείγματα#

Κατανάλωση ενός ορίσματος κατά θέση μέσα σε μέθοδο. Αυτή είναι η κανονική πρώτη γραμμή σχεδόν κάθε αντικειμενοστραφούς μεθόδου της Perl:

sub greet {
    my $self = shift;
    my $name = shift;
    return "hello, $name, from $self";
}

Η ίδια μέθοδος γραμμένη με τομή @_ που αναλύεται ως λίστα. Και οι δύο μορφές είναι ιδιωματικές· η shift υπερισχύει όταν θέλετε να αποσπάσετε τον επικαλούμενο πριν αποφασίσετε τι θα κάνετε με το υπόλοιπο @_:

sub greet {
    my ($self, $name) = @_;
    return "hello, $name, from $self";
}

Κατανάλωση του @ARGV στην κορυφή ενός σεναρίου, ένα όρισμα τη φορά:

my $mode = shift // 'default';       # first CLI arg, or 'default'
my $path = shift // die "need a path\n";
# @ARGV now holds whatever is left

Μια ουρά FIFO: push στην ουρά, shift από την κεφαλή:

my @queue;
push @queue, 'a', 'b', 'c';
while (defined(my $job = shift @queue)) {
    handle($job);
}

Αποαναφορά αναφοράς πίνακα επιτόπου - η shift λειτουργεί στο @$aref ακριβώς όπως σε κατονομασμένο πίνακα:

my $aref = [10, 20, 30];
my $head = shift @$aref;             # 10, $aref now [20, 30]

Οριακές περιπτώσεις#

  • Κενός πίνακας: επιστρέφει undef και αφήνει τον πίνακα ανέγγιχτο. Η shift σε κενό πίνακα δεν είναι σφάλμα.

  • Η πολυπλοκότητα είναι O(n): κάθε υπόλοιπο στοιχείο μετακινείται κάτω κατά μία θέση. Για μεγάλους πίνακες που χρησιμοποιούνται ως ουρές αυτό συσσωρεύεται. Όταν δεν απαιτείται διάταξη FIFO, η pop είναι O(1)· όταν απαιτείται, σκεφτείτε δομή δεδομένων τύπου deque ή ζεύγος στοιβών αντί να κάνετε shift σε πίνακα ενός εκατομμυρίου στοιχείων μέσα σε βρόχο.

  • Η shift χωρίς όρισμα είναι ευαίσθητη στο περιβάλλον βάσει λεξιλογικής θέσης: μέσα σε sub στοχεύει το @_, έξω στοχεύει το @ARGV. Η μετακίνηση μιας γραμμής κώδικα μεταξύ αυτών των εμβελειών αλλάζει σιωπηρά ποιον πίνακα μεταλλάσσει.

  • Tied πίνακες: η shift καλεί τη μέθοδο SHIFT στο tied αντικείμενο αν είναι ορισμένη· διαφορετικά καταφεύγει σε FETCH στο στοιχείο 0, μετά DELETE, μετά σε ακολουθία ζευγών FETCH/STORE για να μετατοπίσει τα υπόλοιπα στοιχεία κάτω, και μετά STORESIZE. Ένας προσαρμοσμένος χειριστής SHIFT σχεδόν πάντα αξίζει να γραφεί για επιδόσεις.

  • Αναφορές πινάκων: η shift @$aref και η shift @{ $expr } λειτουργούν και οι δύο. Η shift $aref (χωρίς το sigil @) ήταν πειραματικό χαρακτηριστικό που προστέθηκε στην Perl 5.14 και αφαιρέθηκε στην 5.24 - είναι συντακτικό σφάλμα στην έκδοση Perl που στοχεύει η pperl.

  • Η shift είναι καταναλωτής-lvalue, όχι lvalue: δεν μπορείτε να αναθέσετε στο αποτέλεσμα της shift για να τροποποιήσετε τον πίνακα. Χρησιμοποιήστε splice ή απευθείας ανάθεση με δείκτη για αυτό.

  • Τιμή επιστροφής σε περιβάλλον λίστας: η shift επιστρέφει πάντα ένα μονό βαθμωτό. Η ανάθεση του αποτελέσματός της σε λίστα - my ($x) = shift @arr - λειτουργεί μόνο επειδή το μονό βαθμωτό γεμίζει την πρώτη θέση λίστας· οι υπόλοιπες θέσεις είναι undef. Χρησιμοποιήστε splice για να αφαιρέσετε πολλά στοιχεία ταυτόχρονα.

Διαφορές από το upstream#

Πλήρως συμβατό με το upstream Perl 5.42.

Δείτε επίσης#

  • pop - αφαιρεί και επιστρέφει το τελευταίο στοιχείο· O(1), η σωστή επιλογή όταν δεν χρειάζεται διάταξη FIFO

  • push - προσαρτά στην ουρά· ζευγαρωμένη με την shift σχηματίζει ουρά FIFO

  • unshift - προσθέτει στην κεφαλή· η αντίστροφη της shift, και επίσης O(n) για τον ίδιο λόγο

  • splice - αφαιρεί, εισάγει, ή αντικαθιστά οποιαδήποτε συνεχόμενη ακολουθία στοιχείων· το γενικό εργαλείο όταν δεν αρκούν οι shift / pop / unshift / push

  • @ARGV - ο προεπιλεγμένος πίνακας τον οποίο καταναλώνει η shift σε εμβέλεια αρχείου

  • @_ - ο προεπιλεγμένος πίνακας τον οποίο καταναλώνει η shift μέσα σε sub· κρατά τη λίστα ορισμάτων του καλούντος