Λί

Λίστες σε R

1 άσκηση

Σχετικά με την έννοια Λίστες

Μια 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"

Πρόσβαση στα στοιχεία μιας λίστας

Υπάρχουν τρεις τρόποι για να το κάνεις αυτό, καθένας χρήσιμος σε διαφορετικά πλαίσια.

1. Με τη σημειογραφία $tag

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

point <- list(x = 5.3, y = 4.2, color = "blue")
#> point$x
#> [1] 5.3
#> point$color
#> [1] "blue"

2. Με τη σημειογραφία [[tag]]

Αυτός έχει το πλεονέκτημα ότι το όνομα της ετικέτας μπορεί να επιλεγεί κατά την εκτέλεση. Πρόσεξε τις διπλές αγκύλες.

want <- "y"
point[[want]] # same as point$y
#> [1] 4.2

3. Με τη θέση

Αυτός λειτουργεί είτε η λίστα έχει ετικέτες είτε όχι. Και πάλι, οι αγκύλες είναι διπλές.

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. Να πάρεις το πρώτο στοιχείο με [[1]]
  2. Να χρησιμοποιήσεις τη συνάρτηση unlist().
pt <-point["color"]

pt[[1]]
#> [1] "red" # simple 1-element vector

unlist(pt)
#> color 
#> "red"  # 1-element vector with name

Πρόσεξε με τη unlist(). Η αναγωγή της δομής είναι χρήσιμη σε αυτή την απλή περίπτωση, αλλά μπορεί να επιφυλάσσει εκπλήξεις με πιο σύνθετα στοιχεία λίστας.

Advanced

Εσωτερική αναπαράσταση

Μια list, όπως και ένα ατομικό vector, αποθηκεύεται σε συνεχόμενες θέσεις μνήμης. Η διαφορά είναι ότι τα αριθμητικά και τα boolean διανύσματα αποθηκεύουν τιμές, ενώ η λίστα αποθηκεύει αναφορές σε αντικείμενα που βρίσκονται αλλού στη μνήμη.

Το να το γνωρίζεις αυτό είναι σπάνια σημαντικό για έναν χρήστη της R, αλλά σε μια πολύγλωσση κοινότητα όπως το Exercism μπορεί να φανεί χρήσιμο σε προγραμματιστές που ξέρουν άλλες γλώσσες.

Επεξεργασία μέσω GitHub Ο σύνδεσμος ανοίγει σε νέο παράθυρο ή καρτέλα

Μάθε την έννοια Λίστες