Python error with a bubble sort function - python

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

Related

Why am I getting this error - searching

I have the following code based on Python School:
EDIT: fixed the indentation of "position" and "return found", and used "raw_input
def linearSearch(item,my_list):
found = False
position = 0
while position < len(my_list) and not found:
if my_list(position) == item:
found = True
position = position + 1
return found
bag = ['book','pencil','pen','note book','sharpner','rubber']
item = raw_input('What item do you want to check for in the bag?')
itemFound = linearSearch(item,bag)
if itemFound:
print('Yes, the item is in the bag')
else:
print('Your item seems not to be in the bag')
When I ran the program, I got the following:
What item do you want to check for in the bag?pencil
Traceback (most recent call last):
File "test.py", line 11, in <module>
item = input('What item do you want to check for in the bag?')
File "<string>", line 1, in <module>
NameError: name 'pencil' is not defined
EDIT: Getting the following error after the edits, although tried to put the item name between quotes
Traceback (most recent call last):
File "test.py", line 12, in <module>
itemFound = linearSearch(item,bag)
File "test.py", line 5, in linearSearch
if my_list(position) == item:
TypeError: 'list' object is not callable
Why am I getting this error?
Thanks.
my_list is a list, index it not call it as a function, so it should be :
if my_list[position] == item:
Another thing, if you are looking for one particular item in my_list, than just return from linearSearch as soon as you found it, no need to keep iterating through the rest of my_list:
if my_list[position] == item:
found = True
return found
The problem is, that you are using python2 and this is python3 code. So it would be best for you to install python3 and this code should run OK. Or in python2 you could you the raw_input function instead of input.
Replace input with raw_input to get a string: input tells Python 2 to evaluate the input string.
That said, your code has more problems: for instance, you increment the position in the wrong place.
I guess this some kind of homework, otherwise there is no need to implement this function just do item in bag. Anyway about the function, there is no need to keep track of the index like that, use range or xrange for that, or having a variable found, just do return True when found and at the end of the function do return False
def linearSearch(item,my_list):
for position in xrange(len(my_list)):
if my_list[position] == item:
return True
return False
you can also use the fact that a list is iterable and do
def linearSearch(item,my_list):
for elem in my_list:
if elem == item:
return True
return False

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

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.

Using str.replace to replace letters in a string at different placeholders of the string

I have a problem that I am working on. The goal of the problem is to take the string placeholder i. If i is an even placeholder, replace the letter at i with the letter at i -1. If the i place holder is odd, then replace the letter i with the letter at i +1.
Here is my code so far:
def easyCrypto (s):
for i in range (0,len(s)-1):
if i % 2 == 0:
str(s).replace(i,((i-1)))
if i % 2 != 0:
str(s).replace(i,((i+2)))
print (s)
My error:
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
easyCrypto('abc')
File "C:/Python/cjakobhomework7.py", line 4, in easyCrypto
str(s).replace(i,((i-1)))
TypeError: Can't convert 'int' object to str implicitly
update!!
New code based on answers:
def easyCrypto (s):
for i in range (0,len(s)-1):
if i % 2 == 0:
s = str(s).replace(s(i),(s(i-1)))
else:
s = s.replace(s(i), s(i + 1))
print (s)
However I still have the following errors:
Traceback (most recent call last):
File "<pyshell#7>", line 1, in <module>
easyCrypto('abc')
File "C:/Python/cjakobhomework7.py", line 4, in easyCrypto
s = str(s).replace(s(i),(s(i-1)))
TypeError: 'str' object is not callable
Any ideas? thank you
Use s[i] instead of s(i), and likewise for the other indexes.
There are two things here:
str.replace does not automatically stringify its arguments. You need to manually convert them into strings. Remember that: "Explicit is better than implicit."
str.replace does not work in-place because strings are immutable in Python. You need to reassign s to the new string object returned by str.replace.
Your code should be:
s = s.replace(str(i), str(i-1))
Also, you can replace if i % 2 != 0: with else: since the condition of the second if-statement can only be true if the first is false:
if i % 2 == 0:
s = s.replace(str(i), str(i-1))
else:
s = s.replace(str(i), str(i+1))
Regarding your edited question, you are trying to call the string s as a function by placing parenthesis after it. You need to use square brackets to index the string:
>>> 'abcde'[0]
'a'
>>> 'abcde'[3]
'd'
>>>
In your case it would be:
s = s.replace(s[i], s[i-1])
As a general rule of thumb, parenthesis (...) are for calling functions while square brackets [...] are for indexing sequences/containers.

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)]

Equivalent of Ruby nil array in Python

In Ruby an empty array returns a nil if the first element is accessed:
2.1.2 :005 > arr = []
=> []
2.1.2 :006 > arr.first
=> nil
2.1.2 :007 > arr[0]
=> nil
I know Python lists are not exactly the same as Ruby arrays, but if you try the equivalent action, you get an error:
>>> l = []
>>> l[0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
How can I instead of an error get a False or None value?
Ideally I'd like an assignment like this to resolve to None / False if the function call returns nothing, but with an inline check rather than a if block.
tp_journal = self.pool.get('account.journal').browse(cr, uid, tp_ids, context=context)[0]
There is no simple way to achieve what you want. The list operations raise an error, period.
However you can work around by:
Accessing something else when the list is empty
Not using indexing
In the first case you can use the fact that empty lists are false and hence (expression) or [None] will evaluate to [None] when the expression returns an empty list, and hence:
((expression) or [None])[0]
The alternative is to avoid using indexing but using iteration and next to get the first element:
next(iter(expression), None)
Unfortunately you must explicitly call iter to get a list iterator.
To extend these methods to any index you can use slicing instead of simple indexing:
((expression)[index:] or [None])[0]
Or:
next(islice(expression, index, None), None)
# or
next(iter(expression[index:]), None)
(where islice is itertools.islice).
This works because slicing doesn't raise errors for out-of-bounds indexes.
Hoever my preferred alternative would be to use a function, if you use that often in your code:
def get_with_default(seq, index):
try:
return seq[index]
except LookupError:
return None
Perhaps you could make use of the short-circuiting nature of the or operator.
seq = [23,42]
print (seq or [None])[0]
#result: 23
seq = []
print (seq or [None])[0]
#result: None
In the above code, seq or [None] evaluates to seq if seq contains any elements, and it evaluates to [None] if seq is empty. Then [0] accesses the first element of whichever list is returned.

Categories