Στο παρασκήνιο κοιτάξτε το Map, Filter και Reduce in Swift

Μια συνάρτηση παίρνει κάποια είσοδο, κάνει κάτι σε αυτήν και δημιουργεί μια έξοδο. Μια συνάρτηση έχει μια υπογραφή και ένα σώμα. Εάν δώσετε την ίδια είσοδο σε μια συνάρτηση, τότε έχετε πάντα την ίδια έξοδο. Αυτός είναι εν συντομία ένας ορισμός για τη συνάρτηση .

Τώρα θα μιλήσουμε περισσότερο για τις λειτουργίες με μια πιο προσεκτική ματιά σε αυτές. Θα διερευνήσουμε λειτουργίες υψηλότερης τάξης στο Swift. Μια συνάρτηση που λαμβάνει μια άλλη συνάρτηση ως είσοδος ή επιστρέφει μια συνάρτηση καλείταιμια λειτουργία υψηλότερης τάξης .

Στο Swift, παίζουμε με χάρτη, φιλτράρισμα, μειώνουμε καθημερινά. Όταν χρησιμοποιούμε αυτές τις λειτουργίες, φαίνεται σαν μαγικό. Σε αυτό το σημείο, ίσως να μην έχετε ιδέα για το τι συμβαίνει πίσω από τα παρασκήνια. Ο χάρτης, το φίλτρο και η μείωση λειτουργούν μέσω των ιδεών και προσεγγίσεων του λειτουργικού προγραμματισμού. Παρόλο που το Swift δεν είναι μια καθαρή λειτουργική γλώσσα, σας επιτρέπει να κάνετε λειτουργικά πράγματα.

Τώρα ας δούμε ένα προς ένα τι συμβαίνει στο παρασκήνιο για αυτούς. Πρώτα θα εφαρμόσουμε τις βασικές εκδόσεις αυτών των λειτουργιών για ορισμένους τύπους δεδομένων και μετά θα προσπαθήσουμε να εφαρμόσουμε μια γενική έκδοση.

Λειτουργία χάρτη

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

Τώρα χρειαζόμαστε μια άλλη συνάρτηση που επιστρέφει έναν νέο πίνακα διπλασιάζοντας κάθε στοιχείο του αρχικού πίνακα. Για αυτό, μπορούμε να το εφαρμόσουμε όπως παρακάτω:

Αν κοιτάξουμε τις παραπάνω δύο λειτουργίες, μπορούμε να διαπιστώσουμε ότι κάνουν βασικά το ίδιο πράγμα. Μόνο η λειτουργικότητα στο εσωτερικό για το βρόχο είναι διαφορετική. Και οι δύο παίρνουν έναν πίνακα ακέραιου ως είσοδο, μετασχηματίζουν κάθε στοιχείο χρησιμοποιώντας ένα βρόχο και επιστρέφουν έναν νέο πίνακα. Βασικά, λοιπόν, το κύριο πράγμα είναι να μετατρέψουμε κάθε στοιχείο σε κάτι νέο.

Δεδομένου ότι το Swift υποστηρίζει συναρτήσεις υψηλότερης τάξης, μπορούμε να γράψουμε μια συνάρτηση που θα λαμβάνει μια σειρά από ακέραιους αριθμούς, θα μετασχηματίζει τη συνάρτηση ως είσοδο και θα επιστρέφει έναν νέο πίνακα εφαρμόζοντας τη λειτουργία μετασχηματισμού σε κάθε στοιχείο του αρχικού πίνακα.

Ωστόσο, υπάρχει ένα πρόβλημα με τα παραπάνω: επιστρέφει μόνο έναν ακέραιο πίνακα. Εάν έχουμε την απαίτηση να μετατρέψουμε τον πίνακα ακέραιων εισόδων σε έναν πίνακα συμβολοσειρών, για παράδειγμα, τότε δεν μπορούμε να το κάνουμε με αυτήν τη λειτουργία. Για να γίνει αυτό, πρέπει να γράψουμε μια γενική συνάρτηση που λειτουργεί για κάθε τύπο.

Μπορούμε να εφαρμόσουμε μια γενική συνάρτηση σε μια επέκταση Array ως εξής:

  1. Δηλώστε μια συνάρτηση χαρτών στην επέκταση συστοιχίας που λειτουργεί με έναν γενικό τύπο Τ .
  2. Η συνάρτηση παίρνει μια συνάρτηση τύπου (Element) -> ; T ως είσοδος
  3. Δηλώστε έναν κενό πίνακα αποτελεσμάτων που κρατά τα δεδομένα τύπου Τ μέσα στη συνάρτηση.
  4. Εφαρμόστε το ίδιο για επανάληψη βρόχου και καλέστε τη συνάρτηση μετασχηματισμού για να μετατρέψετε το στοιχείο σε τύπο Τ
  5. Προσθέστε την τιμή μετατροπής στον πίνακα που προκύπτει

Έτσι λειτουργεί η λειτουργία χάρτη στο Swift. Εάν πρέπει να εφαρμόσουμε τον χάρτηλειτουργία , τότε θα το εφαρμόζαμε όπως παραπάνω. Επομένως, βασικά, δεν κάνει καμία μαγεία να συμβαίνει σε έναν πίνακα - θα μπορούσαμε εύκολα να ορίσουμε τη λειτουργία από εμάς.

Λειτουργία φίλτρου

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

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

Εάν εξετάσουμε προσεκτικά την εφαρμογή των δύο παραπάνω λειτουργιών, τότε μπορούμε να καταλάβουμε ότι κάνουν βασικά το ίδιο πράγμα - μόνο ο τύπος δεδομένων είναι διαφορετικός για τις δύο συστοιχίες. Μπορούμε να το γενικεύσουμε εφαρμόζοντας μια γενική συνάρτηση φίλτρου, η οποία παίρνει έναν πίνακα και μια συνάρτηση ως είσοδο, και ανάλογα με την έξοδο της συνάρτησης includeElement , αποφασίζει εάν θα προστεθεί το στοιχείο στον πίνακα που προκύπτει.

Μειώστε τη λειτουργία

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

Τώρα αντί να έχουμε μια σειρά από ακέραιους, ας πούμε ότι έχουμε μια σειρά από συμβολοσειρές και θέλουμε να συνδυάσουμε όλα τα στοιχεία του πίνακα:

Και οι τρεις λειτουργίες κάνουν βασικά το ίδιο πράγμα. Παίρνουν έναν πίνακα ως είσοδο, αρχικοποιούν μια προκύπτουσα μεταβλητή, επαναλαμβάνουν τον πίνακα και ενημερώνουν την προκύπτουσα μεταβλητή.

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

Έτσι μπορούμε να εφαρμόσουμε τη γενική συνάρτηση με τον ακόλουθο ορισμό:

Η παραπάνω εφαρμογή είναι γενική για κάθε πίνακα εισαγωγής τύπου [Στοιχείο]. Θα υπολογίσει ένα αποτέλεσμα του τύπου Τ . Για να λειτουργήσει, χρειάζεται μια αρχική τιμή τύπου T για να αντιστοιχιστεί σε μια μεταβλητή που προκύπτει. Στη συνέχεια, χρειάζεται μια συνάρτηση τύπου (T, Element) -> T, η οποία θα χρησιμοποιηθεί μέσα στο loop για κάθε επανάληψη για την ενημέρωση της προκύπτουσας μεταβλητής.

Ευχαριστούμε που το διαβάσατε!