# Κατάλογοι

# Μεταβλητές με περισσότερες από μια τιμή

Μέχρι τώρα συναντήσαμε μεταβλητές που κρατούν μια μόνο τιμή. Ωστόσο υπάρχουν τύποι μεταβλητών που μπορούν να κρατήσουν παραπάνω από μια τιμή. Η απλούστερη μεταβλητή αυτού του τύπου λέγεται κατάλογος (list). Να ένα παράδειγμα για το πως χρησιμοποιείται ένας κατάλογος.

    which_one = input("What month (1-12)? ")
    months = ['January', 'February', 'March', 'April', 'May', 'June', 'July',\
    	'August', 'September', 'October', 'November', 'December']
    if 1 <= which_one <= 12:
            print "The month is",months[which_one - 1]

και το αποτέλεσμα:

    What month (1-12)? 3
    The month is March

Σε αυτό το παράδειγμα η μεταβλητή `months` είναι ένας κατάλογος. Η μεταβλητή `months` ορίζεται με την γραμμή `months = ['January', 'February', 'March', 'April', 'May', 'June', 'July',`\` 'August', 'September', 'October', 'November', 'December']` (Σημειώστε ότι μια ανάποδη κάθετος `\` μπορεί να χρησιμοποιηθεί για να χωρίσει μια μακριά γραμμή). Οι αγκύλες `[` και `]` αρχίζουν και τελειώνουν τα ορίσματα που μεταξύ τους χωρίζονται με κόμμα (```,`''). The list is used in `months[which_one - 1]`. Αποτελείται από στοιχείο - τιμές που αριθμούνται από το 0. Με άλλα λόγια αν θέλαμε το Ιανουάριο (January) θα γράφαμε `months[0]`. Δώστε στον κατάλογο έναν αριθμό θέσης και θα σας επιστρέψει την τιμή που κρατάει στην θέση αυτή.

Η εντολή `if 1 <= which_one <= 12:` θα ισχύει μόνο αν το `which_one` είναι διάστημα ανάμεσα στο ένα και το δώδεκα (το δίαστημα που ορίζεται η μεταβλητή όπως στην άλγεβρα).

Μπορούμε να φανταστούμε τους καταλογους σαν σειρές από κουτιά. Για παράδειγμα, τα κουτιά που δημιουργούνται κάπως έτσι: `demolist = ['life',42, 'the universe', 6,'and',7]` φαίνονται παρακάτω:

box number | 0 | 1 | 2 | 3 | 4 | 5
demolist | `life' | 42 | `the universe' | 6 | `and' | 7

Κάθε κουτί αναφέρεται στον αριθμό της θέσης του. Έτσι το `demolist[0]` θα δώσει `'life'`, το `demolist[1]`θα δώσει `42` και ούτω καθ' εξής μέχρι το `demolist[5]` που θα δώσει `7`.

# Περισσότερα για τους Καταλογους

Το παρακάτω παράδειγμα δείχνει ένα σωρό από πράγματα που μπορούμε να κάνουμε με τους καταλογους (και ναι, για πρώτη φορά δεν θα σας ζητήσω να πληκτρολογήσετε το παράδειγμα. σας συνιστώ όμως να ``παίξετε'' με τον κώδικα μέχρι να εξοικειωθήτε αρκετά με τους καταλογους). Πάμε λοιπόν:

    demolist = ['life',42, 'the universe', 6,'and',7]
    print 'demolist = ',demolist
    demolist.append('everything')
    print "after 'everything' was appended demolist is now:"
    print demolist
    print 'len(demolist) =', len(demolist)
    print 'demolist.index(42) =',demolist.index(42)
    print 'demolist[1] =', demolist[1]
    #Next we will loop through the list
    c = 0
    while c < len(demolist):
        print 'demolist[',c,']=',demolist[c]
        c = c + 1
    del demolist[2]
    print "After 'the universe' was removed demolist is now:"
    print demolist
    if 'life' in demolist:
        print "'life' was found in demolist"
    else:
        print "'life' was not found in demolist"
    if 'amoeba' in demolist:
        print "'amoeba' was found in demolist"
    if 'amoeba' not in demolist:
        print "'amoeba' was not found in demolist"
    demolist.sort()
    print 'The sorted demolist is ',demolist

Και το αποτέλεσμα:

    demolist =  ['life', 42, 'the universe', 6, 'and', 7]
    after 'everything' was appended demolist is now:
    ['life', 42, 'the universe', 6, 'and', 7, 'everything']
    len(demolist) = 7
    demolist.index(42) = 1
    demolist[1] = 42
    demolist[ 0 ]= life
    demolist[ 1 ]= 42
    demolist[ 2 ]= the universe
    demolist[ 3 ]= 6
    demolist[ 4 ]= and
    demolist[ 5 ]= 7
    demolist[ 6 ]= everything
    After 'the universe' was removed demolist is now:
    ['life', 42, 6, 'and', 7, 'everything']
    'life' was found in demolist
    'amoeba' was not found in demolist
    The sorted demolist is  [6, 7, 42, 'and', 'everything', 'life']

Είδαμε στο παραπάνω παράδειγμα ένα πλήθος από νέες λειτουργίες. Παρατηρήσατε ίσως ότι μπορείτε απλώς να εμφανίσετε όλη τον καταλογο με το `print`. Η εντολή `append` χρησιμοποιείται για να προσθέσουμε ένα νέο στοιχείο στο τέλος του καταλογου. Η εντολή `len` μας επιστρέφει το πλήθος των αντικειμένων - τιμών υπάρχει σε έναν κατάλογο. Τα έγκυρα ευρετηρια (των αριθμών που μπορούν να χρησιμοποιηθούν μέσα στο []) για έναν κατάλογο βρίσκονται στο διάστημα από 0 ως το `len - 1`. Η εντολή `index` μας λέει το που είναι η πρώτη θέση ενός αντικειμένου μέσα στον καταλογο. Προσέξτε ότι η εντολή `demolist.index(42)` επιστρέφει 1 ενώ η `demolist[1]` επιστρέφει 42. Η γραμμή `#Next we will loop through the list` είναι ένα σχόλιο προς τον προγραμματιστή. Η Python θα αγνοήσει τις γραμμές που ξεκινάνε με `#`. Οι γραμμές:

    c = 0
    while c < len(demolist):
        print 'demolist[',c,']=',demolist[c]
        c = c + 1

δημιουργούν την μεταβλητή `c` η οποία ξεκινά από το 0 και αυξάνεται μόλις φτάσει το τελευταίο στοιχείο του καταλογου. Εν τω μεταξύ η εντολή `print` εμφανίζει το κάθε στοιχείο - τιμή του καταλογου.

Η εντολή `del` χρησιμοποιείται για να διαγραφεί ένα στοιχείο από τον καταλογο. Οι επόμενες γραμμές δείχνουν πως χρησιμοποιείται ο συντελεστής `in` για να ελέγξουμε αν υπάρχει ένα στοιχείο στον καταλογο ή όχι.

Η εντολή `sort` χρησιμοποιείται για να ταξινομήσουμε τον καταλογο. Είναι χρήσιμο για να δούμε τα στοιχεία του καταλογου με την σειρά από τον μικρότερο στον μεγαλύτερο αριθμό ή αλφαβητικά. Προσέξτε όμως γιατί η χρήση της εντολής ανακατανέμει τα στοιχεία της.

Συνοπτικά έχουμε τις παρακάτω εντολές για έναν κατάλογο:

Παράδειγμα | Επεξήγηση
`list[2]` | Δημιουργεί πρόσβαση στο στοιχείο με αριθμό ευρετηριου 2
`list[2] = 3` | ορίζει ως 3 το στοιχείο με αριθμό ευρετηριου 2
`del list[2]` | διαγράφει το στοιχείο με αριθμό ευρετηριου 2
`len(list)` | επιστρέφει το μήκος του καταλογου
`"value" in list` | είναι αληθής εάν η `"value"` είναι στοιχείο του καταλογου
`"value" not in list` | είναι αληθής εάν η `"value"` δεν είναι στοιχείο του καταλογου
`list.sort()` | ταξινομεί τον καταλογο
`list.index("value")` | επιστρέφει τον αριθμό ευρετηριου της πρώτης θέσης που υπάρχει η τιμή `"value"`
`list.append("value")` | προσθέτει το στοιχείο - τιμή `"value"` στο τέλος του καταλογου

Το παρακάτω παράδειγμα χρησιμοποιεί τις εντολές αυτές με έναν πιο χρήσιμο τρόπο:

    menu_item = 0
    list = []
    while menu_item != 9:
            print "--------------------"
            print "1. Print the list"
            print "2. Add a name to the list"
            print "3. Remove a name from the list"
            print "4. Change an item in the list"
            print "9. Quit"
            menu_item = input("Pick an item from the menu: ")
            if menu_item == 1:
                    current = 0
                    if len(list) > 0:
                            while current < len(list):
                                    print current,". ",list[current]
                                    current = current + 1
                    else:
                            print "List is empty"
            elif menu_item == 2:
                    name = raw_input("Type in a name to add: ")
                    list.append(name)
            elif menu_item == 3:
                    del_name = raw_input("What name would you like to remove: ")
                    if del_name in list:
                            item_number = list.index(del_name)
                            del list[item_number]
                            #The code above only removes the first occurance of
                            # the name.  The code below from Gerald removes all.
                            #while del_name in list:
                            #       item_number = list.index(del_name)
                            #       del list[item_number]
                    else:
                            print del_name," was not found"
            elif menu_item == 4:
                    old_name = raw_input("What name would you like to change: ")
                    if old_name in list:
                            item_number = list.index(old_name)
                            new_name = raw_input("What is the new name: ")
                            list[item_number] = new_name
                    else:
                            print old_name," was not found"
    print "Goodbye"

Και να ένα μέρος του αποτελέσματος:

    --------------------
    1. Print the list
    2. Add a name to the list
    3. Remove a name from the list
    4. Change an item in the list
    9. Quit

    Pick an item from the menu: 2
    Type in a name to add: Jack

    Pick an item from the menu: 2
    Type in a name to add: Jill

    Pick an item from the menu: 1
    0 .  Jack
    1 .  Jill

    Pick an item from the menu: 3
    What name would you like to remove: Jack

    Pick an item from the menu: 4
    What name would you like to change: Jill
    What is the new name: Jill Peters

    Pick an item from the menu: 1
    0 .  Jill Peters

    Pick an item from the menu: 9
    Goodbye

Ήταν πράγματι ένας μακροσκελής κώδικας. Ας του ρίξουμε μια ματιά. Η γραμμή `list = []` δημιουργεί την μεταβλητή `list` ως εναν κατάλογο χωρίς τιμές (στοιχεία). Η επόμενη καίρια γραμμή είναι η `while menu_item != 9:`. Αυτή ξεκινάει έναν βρόγχο που δημιουργεί ένα μενού αλληλεπίδρασης του χρήστη με το πρόγραμμα. Οι επόμενες γραμμές εμφανίζουν το μενού και γίνεται έτσι η επιλογή για το ποιο μέρος του προγράμματος θα τρέξει.

Το κομμάτι:

    current = 0
    if len(list) > 0:
            while current < len(list):
                    print current,". ",list[current]
                    current = current + 1
    else:
            print "List is empty"

``διατρέχει'' όλο τον κατάλογο και εμφανίζει κάθε όνομα. Η εντολή `len(list_name)` μας λέει πόσα στοιχεία υπάρχουν μέσα στον κατάλογο. Αν η `len` επιστρέψει `0` σημαίνει ότι ο κατάλογος είναι άδειος.

Μερικές γραμμές πιο κάτω εμφανίζεται η εντολή `list.append(name)`. Χρησιμοποιεί την συνάρτηση `append` για να προσθέσει ένα νέο αντκείμενο στο τέλος του καταλογου. Πηγαίνετε δυό γραμμές παρακάτω και παρατηρήστε το κομμάτι του κώδικα που λέει:

    item_number = list.index(del_name)
    del list[item_number]

Εδώ με την εντολή `index` μπορούμε να βρούμε τον αριθμό του ευρετηριου που θα χρησιμοποιήσουμε για να διαγράψουμε το στοιχείο. Τέλος η εντολή `del list[item_number]` χρησιμοποιείται για να διαγράψουμε το στοιχείο από τον καταλογο.

Το επόμενο κομμάτι

    old_name = raw_input("What name would you like to change: ")
    if old_name in list:
            item_number = list.index(old_name)
            new_name = raw_input("What is the new name: ")
            list[item_number] = new_name
    else:
            print old_name," was not found"

χρησιμοποιεί την συνάρτηση `index` για να βρεί τον αριθμό ευρετηριου `item_number` και ορίζει το νέο όνομα ως `new_name` εκεί που ήταν το παλιό (`old_name`).

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

test.py

    ## This program runs a test of knowledge

    true = 1
    false = 0

    # First get the test questions
    # Later this will be modified to use file io.
    def get_questions():
        # notice how the data is stored as a list of lists
        return [["What color is the daytime sky on a clear day?","blue"],\
                ["What is the answer to life, the universe and everything?","42"],\
                ["What is a three letter word for mouse trap?","cat"]]

    # This will test a single question
    # it takes a single question in
    # it returns true if the user typed the correct answer, otherwise false
    def check_question(question_and_answer):
        #extract the question and the answer from the list
        question = question_and_answer[0]
        answer = question_and_answer[1]
        # give the question to the user
        given_answer = raw_input(question)
        # compare the user's answer to the testers answer
        if answer == given_answer:
            print "Correct"
            return true
        else:
            print "Incorrect, correct was:",answer
            return false

    # This will run through all the questions
    def run_test(questions):
        if len(questions) == 0:
            print "No questions were given."
            # the return exits the function
            return
        index = 0
        right = 0
        while index < len(questions):
            #Check the question
            if check_question(questions[index]):
                right = right + 1
            #go to the next question
            index = index + 1
        #notice the order of the computation, first multiply, then divide
        print "You got ",right*100/len(questions),"% right out of",len(questions)

    #now lets run the questions
    run_test(get_questions())

Δοκιμαστικά αποτελέσματα:

    What color is the daytime sky on a clear day?green
    Incorrect, correct was: blue
    What is the answer to life, the universe and everything?42
    Correct
    What is a three letter word for mouse trap?cat
    Correct
    You got  66 % right out of 3

# Ασκήσεις

Επεκτείνετε τις λειτουργίες του προγράμματος test.py έτσι ώστε να έχει μενου διασύνδεσης του συστήματος με τον χρήστη δίνοντας του την δυνατότητα της επιλογής ανάμεσα στο να δώσει ένα τεστ, να δει τις ερωτήσεις και τις απαντήσεις και να μπορεί να κλείσει το πρόγραμμα. Προσθέστε ένα ακόμη ερώτημα: "What noise does a truly advanced machine make?" (τι ήχο βγάζει ένα πραγματικά προηγμένο μηχάνημα;) με απάντηση: "ping".