Διάλεξη 14ης/16ης Νοεμβρίου 2016

Λίστες

Η λίστα είναι μια ακολουθία στοιχείων στην οποία κάθε στοιχείο αναγνωρίζεται από τον δείκτη του (index). Δηλώνουμε ένα αντικείμενο τύπου list απαρθμώντας τα στοιχεία του μέσα σε τετραγωνικές παρενθέσεις. Η κενή λίστα δηλώνεται ως [] ενώ η λίστα με ένα μόνο στοιχείο, π.χ. τον ακέραιο 1 είναι η [1]. Τα στοιχεία της λίστας απαριθμούνται ξεκινώντας από το μηδέν. Οι τρόποι "τεμαχισμού" (slicing) που είδαμε στις ακολουθίες χαρακτήρων και πλειάδες χρησιμοποιούν τον ίδιο συμβολισμό.


>>> L = []
>>> L = [1, 2, 'three']
>>> print(L)
[1, 2, 'three']
>>> L[2]
'three'
>>> L += [4]
>>> print(L)
[1, 2, 'three', 4]
>>> L[1:3]
[2, 'three']

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


L = [1, 2, 3, 4, 5]
for i in range(len(L)):
    L[i] **= 2

Ένας σημαντικός τρόπος κατασκευής ή επέκτασης/ενημέρωσης μιας λίστας είναι η μέθοδος append:


hwk = []
while True:
    grade = input('Enter your homework grade (null to end): ')
    if not grade: break
    hwk.append(float(grade))

print('You entered', len(hwk), 'homework grades:', L)

Το αποτέλεσμα της χρήσης της μεθόδου append είναι η επέκταση της αρχικά κενής λίστας hwk με τον βαθμό που εισάγει ο χρήστης. Σε αντίθεση με την μέθοδο append, η μέθοδος pop διαγράφει το τελευταίο στοιχείο μιας λίστας. Συγκεκριμένα στοιχεία μιας λίστας μπορεί να αφαιρεθούν με την μέθοδο remove, ενώ είναι δυνατόν να τοποθετήσουμε ένα στοιχείο σε μια συγκεκριμένη θέση με την μέθοδο insert. Οι λίστες μπορεί να περιέχουν στοιχεία τα οποία είναι και αυτά λίστες:


>>> L1 = [1, 2, 3]
>>> L2 = [4, 5, 6]
>>> L3 = L1 + L2
>>> print('L3 =', L3)
L3 = [1, 2, 3, 4, 5, 6]
>>> L1.append(L2)
>>> print('L1 =', L1)
L1 = [1, 2, 3, [4, 5, 6]]
>>> L1.extend(L2)
>>> print('L1 =', L1)
L1 = [1, 2, 3, 4, 5, 6]
>>> L1.pop()
6
>>> print('L1 =', L1)
L1 = [1, 2, 3, 4, 5]
>>> L1.remove(3)
>>> print('L1 =', L1)
L1 = [1, 2, 4, 5]
>>> L1.insert(1, 'Maria')
>>> print('L1 =', L1)
L1 = [1, 'Maria', 2, 4, 5]

Συνοψίζουμε μερικές χρήσιμες μεθόδους για λίστες:

Περισσότερες πληροφορίες για αυτές τις μεθόδους αλλά και άλλες μπορεί να βρει κανείς γράφοντας help('list') στη γραμμή εντολών της Python. Εκτός από τις παραπάνω μεθόδους, οι παρακάτω συναρτήσεις χρησιμοποιούνται συχνά με λίστες:

Ας φτιάξουμε τώρα μια λίστα με τίτλους ταινιών:


movies = ['Inception', 'Doctor Strange', 'Pulp Fiction', 'The Usual Suspects']

Ας προσθέσουμε στη λίστα movies τώρα και τις χρονολογίες εμφάνισής τους και τυπώσουμε τη λίστα movies θα δούμε


>>> movies.insert(1, 2010)
>>> movies.insert(3, 2016)
>>> movies.insert(5, 1994)
>>> movies.append(1995)
>>> print(movies)
['Inception', 2010, 'Doctor Strange', 2016, 'Pulp Fiction', 1994, 'The Usual Suspects', 1995]

Είναι εύκολο να προσθέσουμε και άλλες πληροφορίες στη λίστα movies, για παράδειγμα, τον σκηνοθέτη, τη διάρκεια της ταινίας (σε λεπτά) και τους πρωταγωνιστές:


>>> movies.insert(2, 'Christopher Nolan')
>>> movies.insert(3, 148)
>>> movies.insert(4, ['Leonardo DiCaprio', ['Joseph Gordon-Levitt', 'Ellen Page', 'Tom Hardy']])
...
>>> print(movies)
['Inception', 2010, 'Christopher Nolan', 148, ['Leonardo DiCaprio', ['Joseph Gordon-Levitt', 'Ellen Page', 'Tom Hardy']], 'Doctor Strange', 2016, 'Scott Derrickson', 115, ['Benedict Cumberbatch', ['Chiwetel Ejiofor', 'Rachel McAdams', 'Mads Mikkelsen']], 'Pulp Fiction', 1994, 'Quentin Tarantino', 154, ['John Travolta', ['Uma Thurman', 'Samuel L. Jackson', 'Bruce Willis']], 'The Usual Suspects', 1995, 'Bryan Singer', 106, ['Kevin Spacey', ['Gabriel Byrne', 'Chazz Palminteri', 'Benicio Del Toro']]]

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


>>> for item in movies: print(item)
Inception
2010
Christopher Nolan
148
['Leonardo DiCaprio', ['Joseph Gordon-Levitt', 'Ellen Page', 'Tom Hardy']]
Doctor Strange
2016
Scott Derrickson
115
['Benedict Cumberbatch', ['Chiwetel Ejiofor', 'Rachel McAdams', 'Mads Mikkelsen']]
Pulp Fiction
1994
Quentin Tarantino
154
['John Travolta', ['Uma Thurman', 'Samuel L. Jackson', 'Bruce Willis']]
The Usual Suspects
1995
Bryan Singer
106
['Kevin Spacey', ['Gabriel Byrne', 'Chazz Palminteri', 'Benicio Del Toro']]

το οποίο είναι σίγουρα ευκολότερο να διαβάσει κανείς αλλά, πιθανώς, δεν είναι ακόμα εντελώς ικανοποιητικό. Για παράδειγμα, θα μπορούσαμε να τυπώσουμε καλύτερα τη λίστα των πρωταγωνιστών της ταινίας. Δείτε ότι η ανακύκλωση παραπάνω απλά τυπώνει κάθε στοιχείο της λίστας, ανεξάρτητα του τύπου του. Ιδανικά, θα θέλαμε, όποτε το στοιχείο μιας λίστας είναι και αυτό με τη σειρά του λίστα να εκτυπώνουμε τα στοιχεία της το ένα κάτω από το άλλο. Η Python μας παρέχει τη δυνατότητα να ελέγξουμε τον τύπο ενός στοιχείου χρησιμοποιώντας τη συνάρτηση isinstance(item, type) η οποία ελέγχει αν το αντικείμενο item είναι τύπου type. Θα μπορούσαμε να χρησιμοποιήσουμε τη συνάρτηση isinstance() ως εξής:


def prettyPrint(the_list):
    for item in the_list:
        if isinstance(item, list):
            prettyPrint(item)
        else:
            print(item)

και μετά την εντολή preetyPrint(movies) να πάρουμε:


Inception
2010
Christopher Nolan
148
Leonardo DiCaprio
Joseph Gordon-Levitt
Ellen Page
Tom Hardy
Doctor Strange
2016
Scott Derrickson
115
Benedict Cumberbatch
Chiwetel Ejiofor
Rachel McAdams
Mads Mikkelsen
Pulp Fiction
1994
Quentin Tarantino
154
John Travolta
Uma Thurman
Samuel L. Jackson
Bruce Willis
The Usual Suspects
1995
Bryan Singer
106
Kevin Spacey
Gabriel Byrne
Chazz Palminteri
Benicio Del Toro

Πρόβλημα 1. Γράψτε μια συνάρτηση η οποία επιστρέφει True αν είτε το πρώτο είτε το τελευταίο στοιχείο μιας λίστας είναι ο αριθμός 99.


def is99(L):
    return L[0] == 99 or L[-1] == 99

Πρόβλημα 2. Γράψτε μια συνάρτηση η οποία επιστρέφει True αν η λίστα L περιέχει το στοιχείο x, False διαφορετικά.


def contains(L, x):
    for item in L:
        if item == x:
            return True
    return False

Πρόβλημα 3. Γράψτε μια συνάρτηση η οποία με όρισμα μια λίστα L επιστρέφει μια νέα λίστα M τα στοιχεία της οποίας είναι εκείνα τα στοιχεία της L τα οποία είναι πολλαπλάσια του 3.


def list3k(L):
    M = []
    for i in L:
        if i%3 == 0: M.append(i)
    return M

Πρόβλημα 4. Έστω ότι η λίστα L περιέχει ακέραιους αριθμούς. Γράψτε μια συνάρτηση η οποία επιστρέφει το άθροισμα των στοιχείων της. Στο άθροισμα δεν προσμετρώνται τα στοιχεία της λίστας με απόλυτη τιμή μικρότερη από τρία.


def sum3(L):
    summ = 0
    for num in L:
	if abs(num) < 3: continue
        summ += num
    return summ

Πρόβλημα 5. Γράψτε εντολές οι οποίες αντικαθιστούν κάθε στοιχείο μιας λίστας L με το άθροισμα τoυ προηγούμενου και επόμενου στοιχείου του.


for i in range(1,len(L)-1):
    L[i] = L[i-1] + L[i+1]

Πρόβλημα 6. Γράψτε εντολές Python οι οποίες κατασκευάζουν τη λίστα με στοιχεία $0, 1, 2,\ldots,999$.


L = []
for i in range(1000):
    L = L + [i]

ή, ακόμα καλύτερα,

L = []
for i in range(1000): L.append(i)

Θα δούμε αργότερα δύο ακόμα τρόπους, τους L = [i for i in range(1000)] και τον L = list(range(1000)).

Πρόβλημα 7. Γράψτε μια συνάρτηση η οποία επιστρέφει True αν μια λίστα είναι παλινδρομική, False διαφορετικά.


def isPalindrome(L):
    if len(L) <= 1:
        return True
    return L[0] == L[-1] and isPalindrome(L[1:-1])

Πρόβλημα 8. Έστω L μια λίστα τα στοιχεία της οποίας μπορεί να είναι με τη σειρά τους λίστες. Για παράδειγμα, θα μπορούσαμε να έχουμε L = [1, 2, ['one', 3], [[4]], 'Maria']. Γράψτε μια συνάρτηση η οποία κατασκευάζει μια «μονοδιάστατη» λίστα, αφαιρεί δηλαδή τυχόν εσωτερικές λίστες.


def flatten(L):
    M = []
    for item in L:
        if isinstance(item, list):
            M.extend(flatten(item))
        else:
            M.append(item)
    return M

Πρόβλημα 9. Έστω L μια λίστα τα στοιχεία της οποίας είναι όλα μηδέν ή ένα. Γράψτε εντολές Python οι οποίες ταξινομούν αυτή τη λίστα.


i = 0
j = len(L)-1
while i < j:
    while L[i] == 0: i += 1
    while L[j] == 1: j -= 1
    if i < j:
        L[i] = 0
        L[j] = 1

Πρόβλημα 10. Έστω L μια λίστα τα στοιχεία της οποίας είναι όλα μηδέν ή ένα ή δύο. Γράψτε εντολές Python οι οποίες ταξινομούν αυτή τη λίστα.


i = 0
j = 0
k = len(L)-1
while j <= k:
    if L[j] < 1:
        t = L[i]; L[i] = L[j]; L[j] = t
        i += 1
        j += 1
    elif L[j] > 1:
        t = L[j]; L[j] = L[k]; L[k] = t
        k -= 1
    else:
        j += 1