While trying to create a web crawler, I'm trying to define this function:
#a and b are lists.
def union(a, b):
i = 0
while i <= len(b):
if b[i] in a :
a = a.append(b[i])
i = i + 1
return a
then testing it, I input:
a = [1,2,3]
b = [2,4,6,9]
union(a,b)
It keeps giving me the error
TypeError: argument of type 'NoneType' is not iterable
I've seen a solution for this problem in another thread by editing my condition to if a and b[i] not in a:, but while testing, that only solves it until I append 1 element of b to a, then stops working.
See the updated and commented code below
#a and b are lists.
def union(a, b):
i = 0
while i <= len(b):
if b[i] in a :
# the problem lies here. append returns None
# a = a.append(b[i])
# this should work
a.append(b[i])
i = i + 1
return a
Related
I very new with python and I'm doing an online class to learn the basics. While everything is going well, there are still a things that I don't seem to grasp in python..
Even though I found a much simpler way to solve the bellow problem, I'd still like to understand why my procedure is returning "None" .. Is it mistake with my if statements ? a syntax error ?
Here is the problem:
Define a procedure, union, that takes as inputs two lists.
It should modify the first input list to be the set union of the two lists. You may assume the first list is a set, that is, it contains no repeated elements.
The result we are expecting:
a = [1,2,3]
b = [2,4,6]
union(a,b)
print a
#>>> [1,2,3,4,6]
You will note that, in my procedure, I'm using another procedure to find if a list item is in the other list. Could the problem be coming from that ?
Here is my code:
def find_element(a,b):
if b in a:
return a.index(b)
return - 1
def union(a,b):
i = 0
while i < len(b) - 1:
c = find_element(a,b[i])
if c != -1:
i = i + 1
if c == -1:
a = a.append(b[i])
i = i + 1
return a
a = [1,2,3]
b = [2,4,6]
print(union(a,b))
a = a.append(b[i])
Here, a.append(b[i]) appends b[i] to a and returns 'none' which you have assigned to 'a'.
change this to
a.append(b[i])
and you should atleast get an output.
just in case you may need it.
you code could will be easier to read if you have it like this.
but its nice to challenge yourself.
best,
def union(a, b):
for item in b:
if item not in a:
a.append(item)
return a
a = [1, 2, 3]
b = [2, 4, 6]
x = union(a, b)
print(x)
Here is the code:
def share_diagonal(x0, y0, x, y):
dy = abs(x - x0)
dx = abs(y - y0)
return dy == dx
def col_clashes(list_rows_queens, coluna):
for index in range(coluna):
if share_diagonal(index, list_rows_queens[index], coluna, list_rows_queens[coluna]):
return True
return False
def has_clashes(solucao):
for coluna in range(1, len(solucao)):
if col_clashes(solucao, coluna):
return True
return False
def check_repeat(a):
for i in range(len(a)):
for j in range(len(a)):
if a[i] == a[j]:
return i
return False
def test(x):
print(x)
def main():
# random handle
import random
rng = random.Random()
# makes a list of solutions
solution = list(range(8))
# initializes variables
numbers_found = 0
tries = 0
#makes a list to be appended.
unique = []
# main loop code
while numbers_found < 10:
rng.shuffle(solution)
tries += 1
if not has_clashes(solution) and solution not in unique:
print("Solution {0} found after {1:>} {2:>}".format(solution, tries, "tries"))
tries = 0
numbers_found += 1
unique.append(solution)
solution = list(range(8)) # THIS LINE MADE THE CODE WORK
print("Done. Unique solutions: {0}".format(unique))
main()
When I didn't have the solution = list(range(8)) in the main while loop, I would end up with an infinite loop and if I tried to get around it, the numbers just wouldn't shuffle (I tried making a function to append the numbers to a list = [] and then re-checking for solutions, all of them ended up either equal or changing between a and, i.e. [1,2,3,4],[5,6,7,8],[1,2,3,4],[5,6,7,8]...
Here is the traceback for the infinite loop:
/home/****/PycharmProjects/untitled/venv/bin/python /home/****/PycharmProjects/LearningToThinkLikeAComputerScientist/c14_Exercises/3.py
Solution [5, 2, 4, 7, 0, 3, 1, 6] found after 436 tries
Traceback (most recent call last):
File "/home/****/PycharmProjects/LearningToThinkLikeAComputerScientist/c14_Exercises/3.py", line 63, in <module>
main()
File "/home/****/PycharmProjects/LearningToThinkLikeAComputerScientist/c14_Exercises/3.py", line 51, in main
rng.shuffle(solution) # Shuffles the list solution
File "/usr/lib/python3.6/random.py", line 276, in shuffle
j = randbelow(i+1)
File "/usr/lib/python3.6/random.py", line 231, in _randbelow
if type(random) is BuiltinMethod or type(getrandbits) is Method:
KeyboardInterrupt
Process finished with exit code 1
I have no idea why this is happening, I just would like to understand to further improve my knowledge.
Glancing through the code, this is a manifestation of one of the most common gotchas around mutable objects and name references. Obligatory Recommended reading here.
The issue is that names are just references to the actual underlying python object that they represent. When you append solution to the unique list via unique.append(solution) , unique[0] and solution both are referring to the same object.
rng.shuffle(solution) is shuffling the object referred to by the solution variable in-place, thus solution and unique[0] both reflect the change, because they both still refer to the same object.
A simpler example to demonstrate.
a = [1,2,3]
b = a
print(b)
a.append(4) #modifying the object referred to by a using one of its methods.
print(b) #[1,2,3,4]
print(a is b) #is keyword can be used to check if they are both the same object
print(id(a))
print(id(b)) #both id are same.
And you can go on from there.
a = [1, 2, 3]
b = []
b.append(a)
print(b)
a.append(4)
print(b)
import random
rng = random.Random()
rng.shuffle(a)
print(a)
print(b)
Because of this, after the first time you enter the if block, and unique.append(solution), solution not in unique condition always returns returns False , thus your loop gets stuck because you aren't entering the if block anymore, and so numbers_found does not get updated after.
If you ever need to assign a list but ensure you do not run into this issue, make sure you create a fresh copy of the list.
a = [1,2,3]
b = a.copy()
print(b is a) #false
print(id(a))
print(id(b))
a = [1,2,3]
b = a[:] #slices to create a copy of the entire list.
print(b is a) #false
I have two string list:
A = ['YELLOW']
B = ['BA']
I want to combine these two string using a recursive function to get
['YBAEBALBALBAOBAWBA']
HERE IS my function :
def Combine(A, B):
if len(A) > 0:
return str(A[0]) + str(B) + Combine(A[:0], B)
--
I have no idea how recursive works?
Could someone please help me!
You were very close!
def Combine(A, B):
if len(A) > 0:
return str(A[0]) + str(B) + Combine(A[1:], B) # <-- fix 1
else:
return '' # <-- fix 2
in order to call recursively with the rest of A you should call A[1:]
you took care of the case that len(A) > 0 but forgot to take care of the case that A ran out of characters (the else)
Running
A = 'YELLOW'
B = 'BA'
print(Combine(A, B))
OUTPUT
YBAEBALBALBAOBAWBA
I am trying to match two strings sequentially till the first the non-matched character and then determine the percentage exact match. My code is like this:
def match(a, b):
a, b = list(a), list(b)
count = 0
for i in range(len(a)):
if (a[i]!= b[i]): break
else: count = count + 1
return count/len(a)
a = '354575368987943'
b = '354535368987000'
c = '354575368987000'
print(match(a,b)) # return 0.267
print(match(a,c)) # return 0.8
Is there any built-in method in python already which can do it faster ? For simplicity assume that both strings are of same length.
There's no built-in to do the entire thing, but you can use a built-in for computing the common prefix:
import os
def match(a, b):
common = os.path.commonprefix([a, b])
return float(len(common))/len(a)
I don't think there is such build-in method.
But you can improve your implementation:
No need to wrap the inputs in list(...). Strings are indexable.
No need for count variable, i already carries the same meaning. And you can return immediately when you know the result.
Like this, with some doctests added as a bonus:
def match(a, b):
"""
>>> match('354575368987943', '354535368987000')
0.26666666666666666
>>> match('354575368987943', '354575368987000')
0.8
>>> match('354575368987943', '354575368987943')
1
"""
for i in range(len(a)):
if a[i] != b[i]:
return i / len(a)
return 1
alternative
(Just now saw that the answer below me thought of the same thing while I was editing the post)
def match(l1, l2):
# find mismatch
try:
stop = next(i for i, (el1, el2) in enumerate(zip(l1, l2)) if el1 != el2)
return stop/len(l1)
except StopIteration:
return 1
This is a simplification of my program, I have a hard time understanding why the error occurs and what the solution to it is.
def test(n=0):
a = [];
b = [];
if n == 0:
return a,b
else:
a.append(1);
b.append(2);
for i in range(0,2):
x,y = test(i)
x and y must have different values at each iteration, but since the function returns None at one point and then later it wants to overvwrite it , it will get crash with the error "TypeError" - is there a clean solution, despite using some kind of try - catch machnism?
The following code makes the program run, but it feels like misusing the try-catch mechanism of an earlier design error.
def test(n=0):
a = [];
b = [];
if n == 0:
return a,b
else:
a.append(1);
b.append(2);
for i in range(0,2):
try:
x,y = test(i)
except TypeError:
continue;
Your function test has no return in such a case function automatically return None, while on return you are trying to put returned[0] to x and returned[1] to y. Where as returned is None which is not iterable.
Correct Code :
def test(n=0):
a = [];
b = [];
if n == 0:
return a,b
else:
a.append(1);
b.append(2);
return a,b
for i in range(0,2):
x,y = test(i)
It's not clear what you are trying to do to me.
1) a and b are local arrays so they will never contain more than 1 element.
Is this intended?
2) then your func test has no return in the else part so it will return None.
you try to put None into x and y by iterating over None which cant be done and
gives the error