Μαζευτήκατε πολλοί στη λίστα μου και θα σας διαγράψω όλους 2/3

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

Image result for delete from list

Βασικός στόχος είναι να προσεγγίσουμε το θέμα με τα εργαλεία που αναφέρει το βιβλίο όπως για παράδειγμα η μέθοδος pop που αναφέρθηκε.

Ας υποθέσουμε για αρχή ότι κάθε στοιχείο εμφανίζεται μόνο μία φορά. Έτσι για να χρησιμοποιήσουμε τη μέθοδο αυτή (pop) πρέπει να γνωρίζουμε τη θέση (index) του στοιχείου μέσα στη λίστα. Εάν δεν την ξέρουμε εκτελούμε πρώτα μία σειριακή αναζήτηση εφόσον  τα στοιχεία δεν είναι ταξινομημένα .

a_list = [3,4,7,5,8,9,1,2,0]
item = input("Item to delete=")
i = 0
pos = -1
while i<= len(a_list)-1 and pos == -1:
    if a_list[i] == item:
        pos = i
    else:
        i += 1
if pos != -1:
    print "Item found in position = ", pos
    a_list.pop(pos)
else:
    print "Item not found in the list"       
print a_list
-----------------------------------------------
>>> 
Item to delete=8
Item found in position = 4
[3, 4, 7, 5, 9, 1, 2, 0]
>>> 

Τι γίνεται όμως εάν το στοιχείο που θέλουμε να διαγράψουμε μπορεί να εμφανίζεται περισσότερες από μία φορές. Μπορεί τότε η pop να μας βοηθήσει; Μία σκέψη είναι να διασχίσουμε τη λίστα με την εντολή επανάληψης for και κάθε φορά που βρίσκουμε το στοιχείο να το διαγράφουμε. Ας το δούμε να “δουλεύει”

a_list = [3,4,8,5,8,9,8,2,0]
item = input("Item to delete=")
for i in range(len(a_list)):
    print i,
    if item == a_list[i]:
        print i, a_list.pop(i)

-----------------------------------------------
Item to delete=10
0 1 2 3 4 5 6 7 8
-----------------------------------------------
Item to delete=8
0 1 2 2 8
3 3 8
4 4 8
5 6

Traceback (most recent call last):
 File "C:\Python27\test_remove_item_from_list.py", line 30, in <module>
 if item == a_list[i]:
IndexError: list index out of range

Ουπς. Όταν δεν υπάρχει το στοιχείο είναι ΟΚ, όταν προσπαθούμε να διαγράψουμε το 8 εμφανίζεται λάθος και είναι εμφανές το γιατί, εφόσον ενώ  η λίστα διάσχισης υπολογίζεται μόνο στην αρχή για το αρχικό μέγεθος της λίστας, αφαιρώντας κάθε φορά και ένα στοιχείο το μέγεθος της λίστας αλλάζει(μικραίνει) επιστρέφοντας indexerror.

Για να κάνουμε μία ντρίπλα στον τρόπο διάσχισης.

a_list = [3,4,8,5,8,9,8,2,0]
item = input("Item to delete=")
for i in range(len(a_list)-1,-1,-1):
    print i
    if item == a_list[i]:
        print "\n"
        print i,a_list.pop(i)
print a_list    
----------------------------------------
Item to delete=8
8
7
6

6 8
5
4

4 8
3
2

2 8
1
0
[3, 4, 5, 9, 2, 0]

Διασχίζοντας τη λίστα ανάστροφα δεν επηρεάζεται ο κώδικας από τη αλλαγή του μεγέθους της, εφόσον ο δείκτης i λαμβάνει την τιμή του μήκους της μόνο μία φορά στον υπολογισμό του range στην αρχή.

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

a_list = [3,4,8,5,8,9,8,2,0]
item = input("Item to delete=")
i = 0
while i <= len(a_list)-1:
    print i
    if item == a_list[i]:
        print i, a_list.pop(i)
    else:
        i += 1
print a_list
------------------------------
>>> 
Item to delete=8
0
1
2
2 8
2
3
3 8
3
4
4 8
4
5
[3, 4, 5, 9, 2, 0]

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


Θα δούμε όμως μία άλλη προσέγγιση χωρίς να χρησιμοποιήσουμε τη μέθοδο pop και πάντα μέσα στην ύλη του βιβλίου. Έως τώρα σκεφτόμασταν αφαιρετικά δηλαδή πως θα αφαιρέσουμε στοιχεία από μία λίστα. Ας προσεγγίσουμε το πρόβλημα συνθετικά, δηλαδή πως θα φτιάξουμε μία λίστα η οποία θα περιέχει όλα τα στοιχεία της αρχικής εκτός από αυτά που δεν επιθυμούμε. Έτσι και αλλιώς στη γλώσσα αυτή όπου τα πάντα είναι αντικείμενα (objects) και στιγμιότυπα μίας κλάσης όπως ένας ακέραιος αριθμός, ένας χαρακτήρας, μία λίστα. Αποτελεί πολύ κοινή πρακτική να φτιάχνουμε νέα αντικείμενα.

a_list = [3,4,8,5,8,9,8,2,0]
b_list = []
item = input("Item to delete=")
for element in a_list:
    if item != element:
        b_list.append(element)
print a_list
print b_list
---------------------------------
>>> 
Item to delete=8
[3, 4, 8, 5, 8, 9, 8, 2, 0]
[3, 4, 5, 9, 2, 0]

Λόγω της κοινής αυτής πρακτικής έτσι εγκυκλοπαιδικά να αναφέρουμε ότι η python έχει και μία τεχνική η οποία ονομάζεται list comprehension (κατανόηση λίστας ?) που μπορεί να κάνει τα παραπάνω σε μία γραμμή κώδικα. Να σημειώσουμε ότι δεν εξηγείται στο βιβλίο όποτε δεν τη χρησιμοποιούμε και σε εξετάσεις.

a_list = [3,4,8,5,8,9,8,2,0]
item = input("Item to delete=")
print [element for element in a_list if element != item]
--------------------------------------------------------
>>> 
Item to delete=8
[3, 4, 5, 9, 2, 0]

Σκεφτείτε τώρα για την άλλη φορά μπορείτε να τα πάτε όλα αυτά ένα βήμα παρακάτω ώστε να υπάρχει μεγαλύτερη ευκολία στην επαναχρησιμοποίησή τους ….

Καλό διάβασμα…

Image result for reuse

Κατηγορίες: Προγραμματισμός. Προσθήκη στους σελιδοδείκτες.

Αφήστε μια απάντηση

Η ηλ. διεύθυνση σας δεν δημοσιεύεται. Τα υποχρεωτικά πεδία σημειώνονται με *