I have written a code to get prime numbers upto a certain limit in a list.
As shown above.
import math
primes = []
for i in range(1, 101):
primes.append(i)
primes.remove(10) # Just removing for sake of experiment
tot = math.sqrt(len(primes))
for j in range(2, math.ceil(tot), 1):
for l in range(0, len(primes)):
k = j**2 + l*j
primes.remove(k)
primes.remove(12) # Just removing for sake of experiment
print(primes)
This code is showing error while when it removes elements from nested loop.
Error is shown above.
Traceback (most recent call last):
File "/root/PycharmProjects/love/love.py", line 13, in <module>
primes.remove(k)
ValueError: list.remove(x): x not in list
Why is this happening as this code was able to remove element which is not under nested loop but was unable to remove element which is being removed under nested loops.
Is there any alternate solution to this problem?
You are iterating over a list while you are editing a list, which is something you should never do! When you iterate the list here:
for l in range(0, len(primes)):
You are actually changing the value of len(primes) when you remove the primes! So this causes the code to act irregularly, as:
In the list comprehension, the original list is left intact, instead a new one is created. (SOURCE)
Instead, you can use list comprehension to achieve the same result!
import math
primes = []
for i in range(1, 101):
primes.append(i)
primeslst = []
def isPrime(number):
for i in range(2,int(number/2)+1):
if number%i == 0:
return True
return False
primes = [p for p in primes if not isPrime(p)]
print(primes)
Hope it helps!
Related
I am new to coding in Python and I am struggling with a very simple problem. There is the same question but for javascript on the forum but it does not help me.
My code is :
def filter_list(l):
for i in l:
if i != str():
l.append(i)
i = i + 1
return(l)
print(filter_list([1,2,'a','b']))
If you can help!
thanks
Before I present solution here are some problems you need to understand.
str()
str() creates a new instance of the string class. Comparing it to an object with == will only be true if that object is the same string.
print(1 == str())
>>> False
print("some str" == str())
>>> False
print('' == str())
>>> True
iterators (no +1)
You have i = i + 1 in your loop. This doesn't make any sense. i comes from for i in l meaning i looping over the members of list l. There's no guarantee you can add 1 to it. On the next loop i will have a new value
l = [1,2,'a']
for i in l:
print(i)
>>> 1
>>> 2
>>> 'a'
To filter you need a new list
You are appending to l when you find a string. This means that when your loop finds an integer it will append it to the end of the list. And later it will find that integer on another loop interation. And append it to the end AGAIN. And find it in the next iteration.... Forever.
Try it out! See the infinite loop for yourself.
def filter_list(l):
for i in l:
print(i)
if type(i) != str:
l.append(i)
return(l)
filter_list([1,2,'a','b'])
Fix 1: Fix the type check
def filter_list(l):
for i in l:
if type(i) != str:
l.append(i)
return(l)
print(filter_list([1,2,'a','b']))
This infinite loops as discussed above
Fix 2: Create a new output array to push to
def filter_list(l):
output = []
for i in l:
if type(i) != str:
output.append(i)
return output
print(filter_list([1,2,'a','b']))
>>> [1,2]
There we go.
Fix 3: Do it in idiomatic python
Let's use a list comprehension
l = [1,2,'a','b']
output = [x for x in l if type(x) != str]
print(output)
>>> [1, 2]
A list comprehension returns the left most expression x for every element in list l provided the expression on the right (type(x) != str) is true.
I was trying to implement a backtracking solution to a Leetcode problem (https://leetcode.com/problems/subsets/) and found out an unexpected bug in my code. In the first solution I do out_list.append(curr_array) in line 8 and it outputs me an empty output list.
class Solution:
def subsets(self, nums):
def backtrack(curr_array, curr_idx):
if len(curr_array) > 0:
out_list.append(curr_array)
for idx in range(curr_idx, len(nums)):
curr_array.append(nums[idx])
backtrack(curr_array, idx + 1)
curr_array.pop()
out_list = []
backtrack([], 0)
return out_list
Whereas when I do out_list.append(curr_array[:]), I get the correct answer as output.
class Solution:
def subsets(self, nums):
def backtrack(curr_array, curr_idx):
if len(curr_array) > 0:
out_list.append(curr_array[:])
for idx in range(curr_idx, len(nums)):
curr_array.append(nums[idx])
backtrack(curr_array, idx + 1)
curr_array.pop()
out_list = []
backtrack([], 0)
return out_list
I've been under the impression that list1[:] is the same thing as list1. Can you tell me what am I missing here?
cur_array is a reference to the original list. When you append cur_array to out_list and then later modify cur_array, out_list changes as well.
cur_array[:] is a copy of cur_array (same as cur_array.copy()). When you append cur_array[:] to out_list and then later modify cur_array, out_list does not change because it has its own copy of cur_array.
It looks like you make a misunderstand on list.
>>> a = [] # Here we announce a list
>>> id(a)
82700416
>>> id(a[:])
82700544
As you can see, slice will make a copy of list.
for i in range(0, len(list_stops)):
for j in range(1, len(list_stops[i])):
current = stops_from_stop(list_stops[i][j])
list_stops.extend(current)
for k in range(0, len(current)):
for m in range(0, len(current[k])):
list_stops_x.extend([current[k][m]])
if id_b in list_stops_x:
#rest of code
list_stops is a list of lists. Eg [[1,2,3], [4,5,6]]
list_stops_x is a single list of all the numbers in list_stops. Eg [1,2,3,4,5,6]. Basically used as a condition to enter the rest of the code with a return statement at the end, so the loop does not repeat.
I find that the loop ends after reaching the final index of the first version of list_stops, but I am constantly extending list_stops and want the loop to carry on into the extensions. So for example if I extend [7,8,9] to list_stops in the loop, if id_b is not found I still want it to loop through [7,8,9], but it stops at 6.
Note: This is only a section of the entire function, but I am quite sure the problem lies here. This is also for an introductory programming course, so a simple solution will do :) The full code is below
def find_path(stops, routes, stop_a, stop_b):
id_a = stop_a[0]
id_b = stop_b[0]
unused = unused_stops()
if id_b in list(unused):
return []
total_route = list()
all_stops = stops_from_stop(id_a)
list_stops_x = stops_from_stop_x(id_a)
list_stops = stops_from_stop(id_a)
for index in range(0, len(all_stops)):
if id_b in all_stops[index]:
return find_route(stops, routes, stop_a, stop_b)
for i in range(0, len(list_stops)):
for j in range(1, len(list_stops[i])):
current = stops_from_stop(list_stops[i][j])
list_stops.extend(current)
for k in range(0, len(current)):
for m in range(0, len(current[k])):
list_stops_x.extend([current[k][m]])
if id_b in list_stops_x:
stops_used_rev = [id_b]
last_route = list_stops[len(list_stops) - 1]
current_stop = last_route[0]
stops_used_rev += [current_stop]
for i in range(0, len(list_stops)):
if (current_stop in list_stops[i]) and (list_stops[i][0] == id_a):
stops_used_rev += [id_a]
break
elif current_stop in list_stops[i]:
current_stop = last_route[0]
stops_used_rev += [current_stop]
stops_used = stops_used_rev[::-1]
for index in range(0, len(stops_used) - 1):
total_route.extend(find_route(stops, routes, stops[stops_used[index]], stops[stops_used[index + 1]]))
return total_route
stops_from_stop finds the list stops accessible from the current stop and appends to another list. stops_from_stops_x does the same but extends instead
So the issue is that we use the range(0, len(list_stops)) if we instead use enumerate in the following way, BEWARE INFINITE LOOP, due too we keep adding elements to the list. So be careful, but this should give the desired result. I have changed some part of the code so I could run it.
Enumerate makes it possible to both get the item of the list (val) and the index that we are currently at.
list_stops = [[1,2,3], [4,5,6]]
list_stops_x = [1,2,3,4,5,6]
newer = [[7, 8, 9], [10, 11, 12]]
id_b = 9
for i, val in enumerate(list_stops):
print(val)
for j in range(1, len(list_stops[i])):
current = newer
list_stops.extend(current)
for k in range(0, len(current)):
for m in range(0, len(current[k])):
list_stops_x.extend([current[k][m]])
# if id_b in list_stops_x:
# print("id_b in")
# break
EDIT 1
in your code that was in the edit suggestion you have loops that look like the following:
for i in range(0, len(list_stops)):
...
These should be replace with the following to fix the issue
for i, val in enumerate(list_stops):
...
I have a difficult time of testing the code, but try replace the for loops with the type that i provided and let me know
Edit 2
If we keep adding to the list ofcourse it will loop infinitely unless we exit somewhere. You can see this example that I add elements to list a from list b and then remove the item. As you see from the output we loop eight times so we know it works, you should reflect such changes in your code
a = [1, 2, 3, 4]
b = [5, 6, 7, 8]
for idx, val in enumerate(a):
print("Loop Count: " + str(idx))
if b:
a.append(b[0])
b.remove(b[0])
Loop Count: 0
Loop Count: 1
Loop Count: 2
Loop Count: 3
Loop Count: 4
Loop Count: 5
Loop Count: 6
Loop Count: 7
I'm working out how to remove a specific item from a list.
"peppers", "cheese", "mushrooms", "bananas", "peppers"
I can locate the item "peppers", and change it to "gone!", but I really want to deleting the item, using
del blist[idx]
But that causes an error and I don't know why.
myList = ["peppers", "cheese", "mushrooms", "bananas", "peppers"]
def findInList (needle, haystack):
needle = needle.lower()
findy = []
# loops over list elements
for i in range(0, len(haystack)):
temp = haystack[i].lower()
idx = temp.find(needle)
if (idx != -1): findy.append(i)
return findy
def deleteItemInList(alist, blist):
for i in range(0, len(alist)):
idx = alist[i]
blist[idx] = "Gone!"
# del blist[idx]
# find items in list
mySearch = findInList("Peppers", myList)
# remove item from list
deleteItemInList(mySearch, myList)
print myList
Traceback: as follows
Traceback (most recent call last):
File "delete_in_list.py", line 23, in <module>
deleteItemInList(mySearch, myList)
File "delete_in_list.py", line 16, in deleteItemInList
blist[idx] = "Gone!"
IndexError: list assignment index out of range
Could someone look over the code above and point out where I'm going wrong.
You can use a list comprehension for this.
def removeWord(needle, haystack):
return [word for word in haystack if word.lower() != needle.lower()]
To find an element use this function. Or alternatively just define it as usual:
>>> find = lambda _list, query: [item.lower() for item in _list].index(query.lower())
>>> l = ['red', 'pepper']
>>> q = 'Pepper'
>>> find(l, q)
1
To remove by index just use del:
>>> del l[find(l, q)]
>>> l
['red']
I finally figured it out! Whilst iterating over the list deleting items in the list I was effectively sawing off the branch I was sitting on.
You need to loop over the list in reverse:
def deleteItemInList(alist, blist):
for i in range(len(alist) -1, -1, -1):
idx = alist[i]
del blist[idx]
I'm calling a function within a function. I want it so that every time the function loops (4 instances) it adds the result to a list. In bad programmer terms, something like: for each instance of the loop, run function, add result to list and increment counter, and go again.
Can you help here?
def genDigit():
import random
digit = (random.randint(0, 9))
print(digit)
return
def genNumber():
numList = list
for counter in range(0,4):
'from here on I need to finish the function
Any pointers would be greatly appreciated. I understand in english terms how I would go about finishing this.
Kind regards,
JJP
Instead of printing the digit in your function and then returning nothing, you should return the generated digit. You can then collect those in a list, and return that list. Finally, you print the result.
import random # import once
def genDigit():
digit = random.randint(0, 9)
return digit # return the digit
def genNumber():
numList = list() # add missing ()
for counter in range(0,4):
numList.append(genDigit()) # add digits to list
return numList # return the list
print(genNumber()) # now print the entire list
Or shorter:
def genDigit():
return random.randint(0, 9)
def genNumber():
return [genDigit() for c in range(4)]