רשימות: אופרטורים בסיסיים ואינדקסים#

בסרטון זה למדנו איך לעבוד עם רשימות בפייתון. ראינו איך ליצור רשימה חדשה, איך לשכפל אותה או לחבר שתי רשימות יחד, ואיך להשוות בין רשימות שונות. בנוסף, התנסינו בחיפוש ערכים בתוך רשימה ולמדנו כיצד לגשת לאיברים ספציפיים בעזרת אינדקסים. כל הכלים האלה מאפשרים לנו לנהל אוספי נתונים בצורה גמישה ונוחה.

לנוחותכם חלונית עם הקוד שראינו בסרטון. מוזמנים להריץ בעצמכם:

lst1 = [1,5,4]
lst2 = ["hello", "world"]
lst3 = [23, 5.6, -17, "computer"]
lst4 = []
# print(lst3)
# print(len(lst3))
#print([1,2] + [3])
#print(lst1 + [888])
#print(lst1 + [888,999])
#print(lst1 + lst4)
#print([1,2] * 4)
#print(lst3 * 2)
#print([1,2] == [2,1])
#print([1,2] == [1] + [2])
#print(2 in [1,2])
#print(3 in [1,2])
#print("hello" in lst2)
# print(lst3[0])
# print(lst3[1])
# print(lst3[2])
# i = 3
# print(lst3[i])
print(lst3[4])

בחנו את עצמכם

ניזכר בשתי הרשימות אותן ראינו בסרטון:

lst1 = [1, 5, 4]
lst2 = ["hello", "world"]

נגדיר רשימה נוספת:

lst3 = []

שימו לב - הרשימה lst3 היא רשימה ריקה.

בכל שאלה תופיע פקודה מסוימת המערבת את אחת או יותר מהרשימות הנ”ל. עליכם לסמן מהו הערך המוחזר מהפקודה, או לסמן כי הפקודה מביאה לשגיאה.

דוגמאות:

  1. הפקודה len(lst1) מחזירה 3 - זהו אורך הרשימה lst1.

  2. הפקודה lst3[0] מביאה לשגיאה, שכן הרשימה ריקה ולכן לא ניתן לגשת לאיבר שנמצא באינדקס 0 שלה.

לנוחיותכם, יצירנו חלונית קוד בה תוכלו לבדוק את עצמכם ולהשתכנע בנכונות התשובות. אנו ממליצים לענות תחילה על כל השאלות ולאחר מכן לבדוק את עצמכם בחלונית הקוד.

תזכורת: על מנת להציג את הערך המוחזר של פקודה מסוימת, “עטפו” אותה בפקודת print. למשל: print(len(lst1))

lst1 = [1, 5, 4]
lst2 = ["hello", "world"]
lst3 = []

# check your answers here:

עד כה למדנו שרשימה היא רצף מסודר של איברים. בפייתון יוצרים רשימה על ידי עטיפת האיברים בסוגריים מרובעים ([]) והפרדתם באמצעות פסיקים. חשוב לזכור שאפשר לשים ברשימה איברים מטיפוסים שונים, כלומר מספרים, מחרוזות, ערכים בוליאניים ואף רשימות נוספות – כל אלה יכולים להתקיים באותה רשימה.

my_list = [2, 3, 5, 7, 11]
my_list
[2, 3, 5, 7, 11]
days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
days
['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
pi = ['pi', 3.14159, True]
pi
['pi', 3.14159, True]

גישה לאינדקסים ברשימות#

זוכרים את זה?

אינדקסים וחיתוך (slicing) חלים גם על רשימות בדיוק באותו האופן.

my_list = [2, 3, 5, 7, 11]
print(my_list[0])
print(my_list[4])
print(my_list[-3])
2
11
5
my_list[5]
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
Cell In[20], line 1
----> 1 my_list[5]

IndexError: list index out of range

חיתוך (Slicing)#

גם עם רשימות אפשר לבצע חיתוכים, ממש כפי שעשינו עם מחרוזות. אנחנו משתמשים באותו מבנה מוכר: lst[start:end:step].

כשאנחנו חותכים רשימה, אנחנו בעצם יוצרים ממנה רשימה חדשה, שמכילה את האיברים שבטווח שבחרנו. זה מאפשר לנו לעבוד רק עם חלק מהנתונים, בלי לשנות את הרשימה המקורית.

my_list = [1,2,3,4,5,6,7,8,9,10]

חיתוך מתבצע מאינדקס הstart (כולל) עד אינדקס הend (לא כולל)

print(my_list[1:5]) # slicing
[2, 3, 4, 5]

ניתן להשתמש גם באינדקסים השליליים עבור חיתוך

print(my_list[0:-1]) # forward/backward indexing
[1, 2, 3, 4, 5, 6, 7, 8, 9]

השארת הstart והend ריקים תשתמש בערכים דיפולטיים - תחילת וסוף הרשימה בהתאמה

print(my_list[::2]) # add a step
[1, 3, 5, 7, 9]
print(my_list[::-1]) # reverse
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

כאשר נוצר חיתוך ריק, בו לא נמצאים ערכים, נקבל רשימה ריקה.

print(my_list[3:8:-2]) # output is an empty list. This is NOT an error
[]

כמובן שחיתוך לא משנה את הרשימה המקורית, אלא מייצר רשימה חדשה לחלוטין.

print(my_list) # slicing does NOT change original list!
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
my_list = [1, 2, 3, 4, 5]
new_list = my_list[::2]

print(new_list)
print(my_list)
[1, 3, 5]
[1, 2, 3, 4, 5]

כלומר, ראינו ששליפה של איברים מתוך רשימה דומה מאוד לשליפת תווים ממחרוזת, על-ידי אינדקסים. אבל היתרון הגדול של רשימות על פני מחרוזות הוא שהן mutable - כלומר, ניתנות לשינוי. זה אומר שאפשר לא רק לקרוא ערך שנמצא במקום מסוים ברשימה, אלא גם להחליף אותו בערך חדש. לדוגמה:

lst = [10, 20, 30]
lst[1] = 99
print(lst)   # [10, 99, 30]
[10, 99, 30]

כאן השתמשנו באינדקס כדי להגיע למיקום השני ברשימה, ואז הצבנו שם ערך חדש. פעולה כזו אפשרית כי רשימה היא מבנה נתונים הניתן לשינוי, בניגוד למחרוזות שראינו עד כה, שבהן אי-אפשר לשנות תו קיים אלא רק ליצור מחרוזת חדשה.

תרגול#

ממשו את הפונקציה middle_of_list(lst) אשר מקבלת רשימה lst ומחזירה את האיבר במיקום האמצעי שלה.
אם מדובר ברשימה באורך זוגי, הפונקציה תחזיר את השמאלי מבין האיברים האמצעיים.
שימו לב: יש מגוון דרכים לממש את הפונקציה, וניתן לממש זאת באמצעות שורת קוד אחת בלבד.

def middle_of_list(lst):
    # Write your code here
    pass