Merge sort in Python - `int` object is not iterable - python

Here is merge sort implementation in Python. I am getting the error int object is not iterable when merge_arrays() function is called. Any suggestions will be highly appreciated.
arr = [1,5,4,7,6,8,3,2,9]
def merge_arrays(_arr_left, _arr_right):
sorted_arr = []
left, right = 0, 0
for i in range(0, len(arr)):
if (_arr_left[left] < _arr_right[right]):
sorted_arr.extend(_arr_left[left])
left += 1
else:
print _arr_right[right], right
sorted_arr.extend(_arr_right[right])
right += 1
return sorted_arr
def merge_sort(_arr):
if (len(_arr) <= 1):
return _arr
_arr_left = merge_sort(_arr[:len(_arr)/2])
_arr_right = merge_sort(_arr[(len(_arr)/2):])
return merge_arrays(_arr_left, _arr_right)
try:
merge = merge_sort(arr)
print merge
except Exception as e:
print e

That particular error is coming from the fact that you're saying sorted_array.extend(_arr_left[left]). You're asking for sorted_array to have appended to it every element of the "iterable" _arr_left[left]. But _arr_left[left] isn't really iterable, it's just whatever int is at index left in _arr_left.
If you don't try then except and print the Exception, you'll see a full stack trace that will tell you which line is bad.
File "merge.py", line 27, in <module>
merge = merge_sort(arr)
File "merge.py", line 22, in merge_sort
_arr_left = merge_sort(_arr[:len(_arr)/2])
File "merge.py", line 22, in merge_sort
_arr_left = merge_sort(_arr[:len(_arr)/2])
File "merge.py", line 25, in merge_sort
return merge_arrays(_arr_left, _arr_right)
File "merge.py", line 9, in merge_arrays
sorted_arr.extend(_arr_left[left])
TypeError: 'int' object is not iterable
So you can see the problem starts at line 9. You can also insert import pdb; pdb.set_trace() before you think the Exception comes up to run the python debugger and step through your program's progression to see where the Exception appears.

As other answers have mentioned, you need to change extent to append. However, as you said in comments, you are getting list index out of range error because you are iterating over the size of arr which is 9 but subarrays have much lesser length. Try changing your merging two arrays code to the following.
while (len(_arr_left) > left) or (len(_arr_right) > right):
if (len(_arr_left) > left) and (len(_arr_right) > right):
if (_arr_left[left] < _arr_right[right]):
sorted_arr.append(_arr_left[left])
left += 1
else:
sorted_arr.append(_arr_right[right])
right += 1
elif (len(_arr_left) > left):
sorted_arr.append(_arr_left[left])
left += 1
else:
sorted_arr.append(_arr_right[right])
right += 1
As you can see in the above code, we have to test for various conditions. If both subarrays contains elements, then we compare them to each other and append to sorted_arr depending on the value evaluation. If not then we append values from individual sub-arrays. It would have been easier if instead of using left and right, you were using pop so you wouldn;t have to keep tracking of left and right
Finally, here is the working version of your code. You also need to modify
return merge_sort(...) to sorted_arr = merge_sort(...) return sorted_arr so it doesn't print everytime it returns sorted_arr

In your line 9:
sorted_arr.extend(_arr_left[left])
sorted_arr is a list
_arr_left is a list
left is an int
So, the problem is:
>>> a = [1,2,3,4]
>>> a.extend(5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable
>>>
Solution:
You can use list.append() instead of extend().
>>> a = [1,2,3,4]
>>> a.append(5)
>>> a
[1, 2, 3, 4, 5]
>>>
PS: You might have other issues with your code.

Related

TypeError: 'int' object is not callable python 2.7

I know this question has been asked a lot before, but I can't seem to find any place in my code where I'm binding my list a to an integer value. I've changed all my variable names but to no avail.
Here's the entire code I'm running:
import sys
def powerset(a):
# returns a list of all subsets of the list a
if (len(a) == 0):
return [[]]
else:
allSubsets = [ ]
for subset in powerset(a[1:]):
allSubsets += [subset]
allSubsets += [[a[0]] + subset]
return allSubsets
if __name__ == '__main__':
no_test = int(sys.stdin.readline())
for i in xrange(no_test):
xor_res = 0
len = int(sys.stdin.readline())
numbers_array = map(int,sys.stdin.readline().split())
numbers = []
for i in numbers_array:
numbers.append(i)
maxset = powerset(numbers)
for set in maxset:
if len(set) != 0:
temp = 0
for i in set:
temp = temp^i
xor_res = xor_res ^ temp
print xor_res
And this is the error I'm getting:
Traceback (most recent call last):File "solution.py", line 24, in <module>maxset = powerset(numbers)File "solution.py", line 6, in powerset if (len(a) == 0):TypeError: 'int' object is not callable
Can someone please tell me what's going wrong here?
Thanks!
You've created a variable called len that shadows the built in function len():
len = int(sys.stdin.readline())
When you try to call the len function throughout your code, the interpreter finds the len variable first and tries to call it like a function. Since it's an int, this can't be done and we see the error.
To solve your problem, call your variable something different. In general, avoid creating variables with names like "len", "list", "map", etc, since using these names shadows the built in ones.

ValueError in range function (to print 3^(2^n)) in python

while trying to print the sequence of power(3,2^n), i.e, 3^2,3^4,3^8 , I tried using the following line using range function.Is it possible to use the range function to get the desired output? If so please let me know where did I went wrong.
for i in range(3,1000, i*(i-1)): print (i*i)
for example, the following output is expected for i=3,9,81
i*i:=9,81,6561
But the error is :
Traceback (most recent call last):
File "<pyshell#28>", line 1, in <module>
for i in range(3,1000, i*(i-1)): print (i*i)
ValueError: range() arg 3 must not be zero
How can the step value be zero in this case?
You could use a list comprehension to build a list of all of your powers:
mylist = [3**(2**n) for n in range(1,10)] # or whatever range
and then iterate through the comprehension to print all of your results if you want. You can do other stuff with your results in this loop instead of print them.
for item in mylist:
print(item) # print each item on a new line
i = 2
while 3**i < 1000:
print(3**i)
i *= 2
I'm pretty sure what you want to do is very similar to this question. You want to be calling a list comprehension:
powersofthree = [3**(2**i) for i in range(10)]
which returns
[3, 9, 81, ... ]
Then you can print the result at you leisure.
Also, as many in the comments have pointed out, you used i before it was defined, which is why you encountered an error

Python Force List Index out of Range Exception

I have a list of lists
x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
I want the code to throw an Array Out of Bounds Exception similar to how is does in Java when the index is out of range. For example,
x[0][0] # 1
x[0][1] # 2
x[0-1][0-1] # <--- this returns 9 but I want it to throw an exception
x[0-1][1] # <--- this returns 7 but again I want it to throw an exception
x[0][2] # this throws an index out of range exception, as it should
If an exception is thrown, I want it to return 0.
try:
x[0-1][0-1] # I want this to throw an exception
except:
print 0 # prints the integer 0
I think basically anytime the index is negative, throw an exception.
You can create your own list class, inheriting the default one, and implementing the __getitem__ method that returns the element in a specified index:
class MyList(list):
def __getitem__(self, index):
if index < 0:
raise IndexError("list index out of range")
return super(MyList, self).__getitem__(index)
Example:
>>> l = MyList([1, 2, 3])
>>> l[-1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in __getitem__
IndexError: list index out of range
>>> l[0]
1
>>> l[3]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in __getitem__
IndexError: list index out of range
There is a better way to handle the border cases: just increase the array by two in both dimensions and fill all border with a default (e.g. 0) and never update them. For neighbourhood and update, just search the inner field (index 1..(len-2)), instead of 0..len-1. So, the indexes will never be out of bounds for the neighbourhood search. This elliminates the need for special treatment.
(I did this many years ago for the same usage, but in a different language - Pascal, iirc.)
try:
x[len(x)][0]
except IndexError:
...
This will eventually raise an index error, as len(any_list) is always +1 past the last valid index.
Btw. it is good advise only to catch expected exceptions (the ones you actually want to handle); your code will catch any exception.
Ok, just read your comment. Your original question sounded as if you wanted to provoke an index error.

How to add elements of a list in Python 3.5.5?

My assignment is:
Write a function sumOfPairs that has one parameter of type list. The
list can be empty or contain integers. The length of the list must be
0 or an even number. If the length of the list is not 0 and is not
even, the function should print an error message and return None. You
can assume the list contains only integers. The function returns the
list of the sum of each consecutive pair of the numbers in the list.
Example: If the list is [1,5,2,10,15,2,9,3], the function returns
[6,12,17,12].
My attempt so far is:
def sumOfPairs (list1: list):
if len(list1) != 0 and len(list1)%2 != 0:
print ("Error")
return (None)
else:
x = list1.index(int)
answer = []
while x<=len(list1):
newListValue=list1(x)+list1(x+1)
answer.insert(x,newListValue)
x=x+2
return (answer)
print (sumOfPairs ([1,5,2,10,15,2,9,3]))
Yet it yields the following error upon execution:
Traceback (most recent call last):
File "C:\Users\Andrew\Desktop\lab3.py", line 79, in <module>
print (sumOfPairs ([1,5,2,10,15,2,9,3]))
File "C:\Users\Andrew\Desktop\lab3.py", line 71, in sumOfPairs
x = list1.index(int)
ValueError: <class 'int'> is not in list
How can I fix this?
def sum_of_pairs(l):
if len(l) % 2: # if the length of the list mod 2 has a remainder, the list length is uneven
print("Error, uneven length list")
else: # else, step through the list in pairs and add each pairing
return [l[i]+ l[i+1] for i in range(0,len(l),2)]
In [3]: (sum_of_pairs([1,5,2,10,15,2,9,3]))
Out[3]: [6, 12, 17, 12]
A python function that does not specify a return value as in the if len(l) % 2: will return None by default so we do not need to explicitly return None.
In [11]: l = [1,5,2,10,15,2,9,3]
In [12]: [sum(pair) for pair in zip(l[0::2],l[1::2])]
Out[12]: [6, 12, 17, 12]
I don't particularly like your approach here, but let's take a look at the error specifically.
Traceback (most recent call last):
File "C:\Users\Andrew\Desktop\lab3.py", line 79, in <module>
print (sumOfPairs ([1,5,2,10,15,2,9,3]))
File "C:\Users\Andrew\Desktop\lab3.py", line 71, in sumOfPairs
x = list1.index(int)
ValueError: <class 'int'> is not in list
Now look at the line it occurs on, and try to say it in English
x equals the first index in list1 where the value is 'int'
Note that it's not the value is AN int! This is crucial, and is the reason for the error. Your list does not INCLUDE the class int. That would be something like:
[1,2,3,int,5,6,7,8] # not your list
Much easier would be to test that ALL your indices contain ints, then just iterate through the list. Let's try that (even though your exercise says otherwise, partially to keep you from just copy/pasting this!! :D)
def sum_of_pairs(lst: list):
if len(lst) == 0 or len(lst) % 2 != 0:
raise ValueError("Invalid list length")
# makes more sense to raise an exception here than print an error
if any(not isinstance(int, el) for el in lst):
# if any element is not an int:
raise ValueError("Invalid list contents")
result_list = []
for element in lst:
first_el = element
second_el = next(lst)
# advance the iterator once to grab the next element
result_list.append(first_el + second_el) # add them and append
return result_list
Or even easier if you know how to use the grouper recipe, which is in the pydocs for the itertools module here:
def grouper(iterable, n):
return zip(*iter([iterable])*n)
def sum_of_pairs(lst: list):
# validate here, I'm not going to re-write it
return [sum(pair) for pair in grouper(lst, 2)]

Python error with a bubble sort function

For this function for some reason I get errors, and I can't figure out what's wrong with it.
def bubbleSort(lis):
for pas in lis:
for i in pas:
if lis[i] > lis[i+1]:
lis[i],lis[i+1] = lis[i+1],lis[i]
I get the following errors:
Traceback (most recent call last):
File "<pyshell#5>", line 1, in <module>
bubbleSort(hello)
File "C:/Users/albert/Desktop/test.py", line 4, in bubbleSort
for i in pas:
TypeError: 'int' object is not iterable
Assuming lis is a list of integers, pas will be a single integer. for i in pas: fails because there are no is in a single integer.
Bubble sort is typically done with an outer loop that goes while there are any changes, and an inner loop that iterates over n-1 indices, not list elements. You can find a standard implementation in many places, here's the rosetta code one:
def bubble_sort(seq):
"""Inefficiently sort the mutable sequence (list) in place.
seq MUST BE A MUTABLE SEQUENCE.
As with list.sort() and random.shuffle this does NOT return
"""
changed = True
while changed:
changed = False
for i in xrange(len(seq) - 1):
if seq[i] > seq[i+1]:
seq[i], seq[i+1] = seq[i+1], seq[i]
changed = True
return None

Categories