Linear search in Python - always going to else statement - python

I'm a beginner that is currently working on a program with Python for fun and I am attempting to complete a linear search for a given list. Instead of the program returning the index of the value that is being searched for in the list, it is returning the else condition.
I created another function which is called getVal and this is so that the output of getVal will be passed into the linear search function as one of the parameters/arguments.
How would I be able to correct this so that the index number of the value being searched for in the linear search function will be the output? Any help will be greatly appreciated.
def getVal():
userNum = int(input("Enter a number: "))
return userNum
if userNum != int:
get Val
def linearSearch(searchList, getVal):
for i in range(len(searchList)):
if i == getVal:
return searchList.index(i)
else:
return "Value not found"
getVal()
linearSearch(searchList, getVal)
searchList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Welcome to Python - this is the wrong way for searching in a list.
You are comparing the value you want to find to indexes (result of range) instead of to actual values in the list.
Your else clause instructs the function to return immediately after the first check (in the first iteration of the loop) fails.
To make a for loop in Python iterate over both list values and their indexes you need to use the enumerate function, like this:
def linearSearch(searchList, searchVal):
for index, value in enumerate(searchList):
if value == searchVal:
return index
# this line must only be reached if the loop ends without finding a match!
return "Value not found"
Note also that while Python does allow a function to return different types of values, it is bad practice to have a function return a string in one case and a number in another.
Especially since your function can be used to search for lists containing strings, or any other type of data.
Instead, if match is not found, your function should return None.
You can than check for that specific value and print the appropriate error message:
val = getVal()
res = linearSearch(searchList, val)
for is not None:
print("{} found at index {}".format(val, res))
else:
print("Value not found")
Finally, your getVal function will not check if the value is an integer as you expected, and instead will crush the program if something that isn't an integer is entered by the user.
Usually, testing input for integer is done with a try .. except block, but since you are new to Python, you may not have reached the topic of exceptions yet here are several suggestions on other ways of checking if you got an integer:
How can I check if a string represents an int, without using try/except?

A couple of issues with your code:
if userNum != int: get Val - this will never execute because it's after a return statement, and it contains a syntax error (get Val), and you're comparing userNum which is an integer, with int which is a type
in the for loop "Value not found" would always be returned except if the user wanted to find the 1st element
the way you're calling getVal() - you're not assigning the result to any variable
you're passing getVal as argument to linearSearch but getVal is a function, not the value input by user
Fixed code:
In [1]: def getVal():
...: userNum = int(input("Enter a number: "))
...: return userNum
...:
...: def linearSearch(searchList, val):
...: for i, item in enumerate(searchList):
...: if item == val:
...: return i
...: else:
...: return "Value not found"
...:
...: val = getVal()
...: searchList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
...: linearSearch(searchList, val)
...:
...:
Enter a number: 3
Out[1]: 2

Related

Python Review: Why doesn't code 1 produce same result as code 2?

Why does code 1 output 28 (not what I want) but code 2 outputs [7, 14, 21, 28] (what I want)?
#Code 1
def dog_years(age):
return age * 7
def my_pets_age(func, param_list):
for i in param_list:
func(i)
return func(i)
dog_age = my_pets_age(dog_years, [1, 2, 3, 4])
print(dog_age)
Is there a way for me to write this so that I don't need to create a result variable with an empty array?
#Code 2
def dog_years(age):
return age * 7
def my_pets_age(func, param_list):
result = []
for i in param_list:
result.append(func(i))
return result
dog_age = my_pets_age(dog_years, [1, 2, 3, 4])
print(dog_age)
In code 1, you're not storing the value returned by func(i) anywhere on each iteration. The value is computed and then just thrown away. Then, once the loop is done, the value of i is 4 because that's the last value in the param_list so you return func(4) which is 28.
In the second code, you're actually storing the intermediate values by appending them to the result array.
You can rewrite the second code as:
def my_pets_age(func, param_list):
return [func(i) for i in param_list]
Look at your code #1. Where do you use the result of the func calls from the loop? (Hint: You don't)
There are only four ways information leaves a function:
Through the return value
(For generators) Through a yield expression
Via an exception being raised
By changes to external state (storing to globals, attributes of outside objects or self, etc.)
The only one of those that applies in either example is #1. In the first block of code, you ignore everything you do in the loop aside from the assignment to i, so all it does is return func(i) where i is the last value looped over. In the second block of code, you build a list of all the results and return that, so you get all of the results, not just the last one.

Should the return value of a function be assigned to a variable even if the variable is not used?

Just for example let's say I have a function to create an entry in a list, database, etc. and that function returns the id of that entry. Should I always assign the return value of that function to a variable for readability, consistency, or later use, or should I just omit it since it's not being used? Some code that may demonstrate my point is included below:
def add_to_list(val, arr):
arr.append(val)
return len(arr) - 1
def weird_function(val, arr):
# print the index of the new element if the element is an odd number
if val % 2:
idx = add_to_list(val, arr)
print(idx)
else:
add_to_list(val, arr)
# idx = add_to_list(val, arr)
Should idx = be included in the else statement for consistency's sake?
There's no need to store the value in idx variable if you're not going to use it anywhere. A better approach to improve the readability would be-
def add_to_list(val, arr):
arr.append(val)
def weird_function(val, arr):
# print the index of the new element if the element is an odd number
if val % 2:
print(len(arr))
add_to_list(val, arr)
Should idx = be included in the else statement for consistency's sake?
It just depends on if you want to use idx later on. In your example you're not using, and so it need not be included.
There are cases, where you get a meaningful return value. For example you can have a file update function that will return true if a file was opened and written to successfully, else will return false. In such cases you might want to store the returned values into a log file or something.
Since you've asked this question, I assume you're fairly new to programming (or at least to Python), which means you might not really be working on anything "high end" at the moment. Therefore don't worry about saving anything.
The specific function you've written can be simplified to
def weird_function(val, arr):
if val % 2:
print(add_to_list(val, arr))
else:
add_to_list(val, arr)

For Loop function only returning the same value

I am trying to create a function that accepts a list (of integers) and an integer value and returns the number of elements in the list that are less than the given value. However, the code I have so far only ever returns 1 or 0 and I am not sure why. Can anyone help?
def lesser_than(alist, value):
"""
Returns: number of elements in alist strictly less than value
Example: lesser_than([5, 9, 1, 7, 89], 6) evaluates to 2
Parameter alist: the list to check (WHICH SHOULD NOT BE MODIFIED)
Precondition: alist is a list of ints
Parameter value: the value to compare to the list
Precondition: value is an int
"""
ret = 0
for a in alist:
a = int(a)
value = int(value)
if a < value:
ret += 1
return ret
You have your return in the for loop; it'll return as soon as the first entry is done. Remove a level of indentation on return ret.
This is because your return statement is in the for loop causing it to return at the first value less than the input. Move it outside the loop.
def lesser_than(alist,value):
"""
Returns: number of elements in alist strictly less than value
Example: lesser_than([5, 9, 1, 7, 89], 6) evaluates to 2
Parameter alist: the list to check (WHICH SHOULD NOT BE MODIFIED)
Precondition: alist is a list of ints
Parameter value: the value to compare to the list
Precondition: value is an int
"""
ret = 0
value = int(value) #moved this outside the loop as it's only needed once
for a in alist:
a = int(a)
if a < value:
ret += 1
return ret

Improving Python user defined max function

I am new to programming and am trying to understand how to "think" more programmatically in Python. I wrote a function that returns the largest element in an array without using max:
def max_userdefined(array):
"""
Finds largest value of nonempty array of numbers in O(n)
:param: list/tuple of values
:return: max value
"""
try:
assert isinstance(array, list or tuple)
result = array[0]
for element in array:
if element > result:
result = element
return result
except IndexError:
return 'Please pass in a nonempty array'
except AssertionError:
return 'Please pass in a list or tuple'
except TypeError:
return 'Please make sure elements of array are all floats or ints'
How can I improve the above code? Open to any criticism or if anyone can recommend a good Pythonic style guide.
def max_userdefined(array):
myMax = l[0]
for num in l:
if myMax < num:
myMax = num
return myMax
print max_userdefined ([1,2,3,4,5])
Output
5
Or You can do something like following by using sorted.
def max_userdefined(array):
return sorted(array)[-1]
>>> def umax(array):
global biggest
for num in array:
if num > biggest:
biggest = num
>>> biggest = int()
>>> nums = (1, 9, 6, 4, 5, 3, 2, 7, 0)
>>> umax(nums)
>>> biggest
9
For returning the greatest number from a list the simple algorithm followed is compare two numbers and keep the larger number in a variable, then print the variable OR you can use python shortcut using sort.
Using user defined function:
def greatest_ele_list(listobj):
greatest=listobj[0]
for i in range(len(listobj)):
if listobj[i]>greatest:
greatest=listobj[i]
else:
pass
return greatest
print greatest_ele_list([4,5,3,8,1])
Using sort:
def greatest_ele_list(listobj):
listobj2=listobj.sort()
return listobj2[-1]
print greatest_ele_list([4,5,3,8,1])
Output: >>> 8

How to count the number of letters in a string with a list of sample?

value = 'bcdjbcdscv'
value = 'bcdvfdvdfvvdfvv'
value = 'bcvfdvdfvcdjbcdscv'
def count_letters(word, char):
count = 0
for c in word:
if char == c:
count += 1
return count
How to count the number of letters in a string with a list of sample? I get nothing in my python shell when I wrote the above code in my python file.
There is a built-in method for this:
value.count('c')
functions need to be called, and the return values need to be printed to the stdout:
In [984]: value = 'bcvfdvdfvcdjbcdscv'
In [985]: count_letters(value, 'b')
Out[985]: 2
In [987]: ds=count_letters(value, 'd') #if you assign the return value to some variable, print it out:
In [988]: print ds
4
EDIT:
On calculating the length of the string, use python builtin function len:
In [1024]: s='abcdefghij'
In [1025]: len(s)
Out[1025]: 10
You'd better google it with some keywords like "python get length of a string" before you ask on SO, it's much time saving :)
EDIT2:
How to calculate the length of several strings with one function call?
use var-positional parameter *args, which accepts an arbitrary sequence of positional arguments:
In [1048]: def get_lengths(*args):
...: return [len(i) for i in args]
In [1049]: get_lengths('abcd', 'efg', '1234567')
Out[1049]: [4, 3, 7]
First you should probably look at correct indenting and only send in value. Also value is being overwritten so the last one will be the actual reference.
Second you need to call the function that you have defined.
#value = 'bcdjbcdscv'
#value = 'bcdvfdvdfvvdfvv'
value = 'bcvfdvdfvcdjbcdscv'
def count_letters(word, char):
count = 0
for c in word:
if char == c:
count += 1
return count
x = count_letters(value, 'b')
print x
# 2
This should produce the result you are looking for. You could also just call:
print value.count('b')
# 2
In python, there is a built-in method to do this. Simply type:
value = 'bcdjbcdscv'
value.count('c')

Categories