Hello everybody,
i am a beginner in Python and i am learning Data Structures now.
Could anybody help me to understand why two codes below produce different results?
Hello everybody,
i am a beginner in Python and i am learning Data Structures now.
Could anybody help me to understand why two codes below produce different results?
You may copy these two codes in this online Python compiler and visual debugger, click âVisualize Exercutionâ and take notice how the value of i
and how the content of the list roll_number
change in each iteration of the for
loop, then you may find thereâs something unusual in the running of the second code.
It can also be useful to put some print statements within your loop to see whatâs happening to your i
variable and list at each iteration of the loop.
Second example looks like youâre trying to repair a car while someone is driving it.
When you edit a list while iterating through, you will get strange results. The index will change. You should make a copy and update accordingly.
Hello,
I have two rules for you as the beginner, try to remember forever.
list=[47,64,69,37,76,83,105,97]
new_list=list
here is one rule for you as the beginner - âNever change an element of the list in case of for loopâ. Itâs causing Index Error. Instead of, you should to put in another list.
print("CASE 1")
roll_number=[47,64,69,37,76,83,105,97]
sample_dict={'Jhon':47,'Emma':69,'Kelly':76,'Jason':97}
sample_dicts=list(sample_dict.values())
roll_number_new=[]
for rnum in roll_number:
if rnum in sample_dicts:
roll_number_new.append(rnum)
print(f"Final outcome: {roll_number_new}")
Here is an example with for in range() loop, if you try to remove it inside of the loop, it raise IndexError, I handle with try-except.
print("CASE 2")
roll_number1=[47,64,69,37,76,83,105,97]
for ind in range(len(roll_number1)):
try:
if roll_number1[ind] not in sample_dicts:
roll_number1.remove(roll_number1[ind])
except IndexError:
print("You already removed that element")
print(f"Final outcome: {roll_number1}")
I hope it would be helpful for you.
Hi Aleks! Thank you very much for your detailed explanation, i appreciate it. Thanks
You should not use the python built list to name a list. Doing a copy is fine.
Take this example
alist = [1,2,3,4,5]
#copying blist
blist = alist
#using copy
clist = alist.copy()
#pop element
blist.pop()
# alist changes because they are both pointing to the same thing
print(f'alist -> {alist}')
print(f'blist -> {clist}')
#clist doesn't change because it's a different pointer
print(f'clist -> {clist}')
See Python&Math
I havenât seen anyone explain whatâs going on and what the difference is so Iâll go ahead and do that. Whatâs happening in the first set of code, where you are modifying the original list, is that as you remove items, the for-in loop is skipping past indices its already scanned, for efficiencyâs sakes. You could easily create something using this methodology, and have it return the output you expect, but thatâd be a confirmation bias, meaning that although your output was correct, the method of getting that output was actually not.
When you did it the 2nd way, by copying the list, the indices in the original list remained intact, allowing the for loop to execute in the way you expect. That is a more resource intensive way if you have large lists, but it does still work.
There are a lot more memory efficient ways to do something like this, in as little as one line of code, but something tells me you havenât gotten into using lambda
s or filter
s quite yet.
Edit:
I meant to add the one liner solution for this:
roll_number = [47, 64, 69, 37, 76, 83, 105, 97]
sample_dict = { 'Jhon':47, 'Emma':69, 'Kelly':76, 'Jason':97 }
# A single line, memory efficient method of reducing the list to only values present in the sample_dict values
roll_number_new = list(filter(lambda i: i in sample_dict.values(), roll_number))
print(roll_number_new)
This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.