Μια list στη R είναι μια διατεταγμένη συλλογή στοιχείων, που διαφέρει από τα vectors με μερικούς τρόπους:
numeric με character).Οι αναλογίες με άλλες γλώσσες δεν είναι ακριβείς.
Μια list της R μοιάζει κάπως με ένα λεξικό της Python, αλλά η list είναι διατεταγμένη και η πρόσβαση σε αυτήν γίνεται με αριθμητική θέση.
Μοιάζει κάπως με τη struct της C, με τη διαφορά ότι η list μπορεί εύκολα να επεκταθεί κατά την εκτέλεση.
Το να δίνεις ονόματα (που συχνά αποκαλούνται "ετικέτες") στα στοιχεία είναι πιο συνηθισμένο στις λίστες απ' ό,τι στα διανύσματα:
list(x = 5.3, y = 4.2, color = "blue")
#> $x
#> [1] 5.3
#> $y
#> [1] 4.2
#> $color
#> [1] "blue"
Ωστόσο, οι ετικέτες είναι προαιρετικές και τότε η R θα χρησιμοποιήσει απλώς αριθμούς θέσης:
list(5.3, 4.2, "blue")
#> [[1]]
#> [1] 5.3
#> [[2]]
#> [1] 4.2
#> [[3]]
#> [1] "blue"
Υπάρχουν τρεις τρόποι για να το κάνεις αυτό, καθένας χρήσιμος σε διαφορετικά πλαίσια.
$tag
Πολύ συνηθισμένος αν τα ονόματα των ετικετών είναι γνωστά εκ των προτέρων.
point <- list(x = 5.3, y = 4.2, color = "blue")
#> point$x
#> [1] 5.3
#> point$color
#> [1] "blue"
[[tag]]
Αυτός έχει το πλεονέκτημα ότι το όνομα της ετικέτας μπορεί να επιλεγεί κατά την εκτέλεση. Πρόσεξε τις διπλές αγκύλες.
want <- "y"
point[[want]] # same as point$y
#> [1] 4.2
Αυτός λειτουργεί είτε η λίστα έχει ετικέτες είτε όχι. Και πάλι, οι αγκύλες είναι διπλές.
point[[3]] # same as point$color
#> [1] "blue"
Απλό: η εκχώρηση σε ένα στοιχείο θα το τροποποιήσει αν υπάρχει ή θα το εισαγάγει αν είναι νέο.
point$color <- "red"
point$trust <- TRUE
# str() gives more compact output than the default display
str(point)
#> List of 4
#> $ x : num 5.3
#> $ y : num 4.2
#> $ color: chr "red"
#> $ trust: logi TRUE
Για να διαγράψεις, εκχώρησε NULL στο στοιχείο που δεν θέλεις.
point$trust <- NULL
str(point)
#> List of 3
#> $ x : num 5.3
#> $ y : num 4.2
#> $ color: chr "red"
Η κλάση vector είναι τεχνικά γνωστή ως atomic vector, επειδή μπορεί να περιέχει μόνο ατομικές τιμές: numeric, character, boolean κ.λπ.
Επειδή μια list μπορεί να περιέχει άλλες λίστες, είναι επίσης γνωστή ως recursive vector.
Πέρα από τεχνικό ζήτημα ονοματολογίας, αυτό μας υπενθυμίζει ότι οι λίστες μπορούν να έχουν οσοδήποτε σύνθετη δομή. Ευθύνη του προγραμματιστή είναι να καταλαβαίνει τι θα πάρει όταν αποκτά πρόσβαση σε ένα στοιχείο λίστας.
Μερικά από τα παραπάνω παραδείγματα χρησιμοποίησαν διπλές αγκύλες [[ ]] για την πρόσβαση σε στοιχεία λίστας.
Αυτό θα επιχειρήσει να αναγάγει το στοιχείο στον υποκείμενο τύπο του, κάτι που είναι χρήσιμο αν θέλεις απλώς έναν αριθμό ή μια συμβολοσειρά.
Η χρήση μονών αγκυλών [ ] δεν κάνει αυτή την αναγωγή, και η τιμή που επιστρέφεται είναι μια υπολίστα.
point[["color"]]
#> [1] "red" # flattened
point["color"]
#> $color
#> [1] "red" # sublist
Ακόμα κι αν η υπολίστα δεν είναι αυτό που θα περίμενε ένας αρχάριος προγραμματιστής της R, καλό είναι να την έχεις υπόψη σου.
Για μέγιστη ευελιξία, πολλές βασικές συναρτήσεις της R επιστρέφουν μια list, ακόμα κι όταν αυτή περιέχει μία μόνο ατομική τιμή, όπως εδώ.
Για να τη μετατρέψεις σε διάνυσμα υπάρχουν δύο δυνατότητες.
[[1]]
unlist().pt <-point["color"]
pt[[1]]
#> [1] "red" # simple 1-element vector
unlist(pt)
#> color
#> "red" # 1-element vector with name
Πρόσεξε με τη unlist().
Η αναγωγή της δομής είναι χρήσιμη σε αυτή την απλή περίπτωση, αλλά μπορεί να επιφυλάσσει εκπλήξεις με πιο σύνθετα στοιχεία λίστας.
Μια list, όπως και ένα ατομικό vector, αποθηκεύεται σε συνεχόμενες θέσεις μνήμης. Η διαφορά είναι ότι τα αριθμητικά και τα boolean διανύσματα αποθηκεύουν τιμές, ενώ η λίστα αποθηκεύει αναφορές σε αντικείμενα που βρίσκονται αλλού στη μνήμη.
Το να το γνωρίζεις αυτό είναι σπάνια σημαντικό για έναν χρήστη της R, αλλά σε μια πολύγλωσση κοινότητα όπως το Exercism μπορεί να φανεί χρήσιμο σε προγραμματιστές που ξέρουν άλλες γλώσσες.