Finding a maximum in a defined part of a list - python

Being a beginner, I am not sure that I am formulating the question correctly, but here is my problem:
I am trying to define a function where, given a list, a beginning and an end, the program would return the maximum of that list between the postions 'beginning' and 'end'. Here is my code:
def eleMax(liste, debut=0, fin=99999999):
if fin > len(liste):
fin=len(liste)
for i in liste:
while i in range(liste[debut], liste[fin]):
return max(i)
However there seems to be several problems. Here, I get: 'list index out of range'. In other versions of this code I also kept getting 'int object is not iterable', which I think is linked to debut and fin being arguments.
Is this approach even possible? Or should I try a whole different method?

You are returning the maximum of one single value.
You need to instead slice the list:
def eleMax(liste, debut=None, fin=None):
return max(liste[debug:fin])
There is no need to constrain the end value to the length of the list. You can leave debut and fin set to None instead, to fall back to the Python defaults (which are 0 and the length of liste, respectively).

Related

python logic setting variable to none

Ive done enough research to understand my logic (I believe):
I have python code to set a variable to None so that at the db level it stores the value of this variable to Null.
Logic looks like:
# when properly set to something other than `None` an example value might be: ['6.1 ', 'Medium'
thesev=cve.find("span", class_="label-warning").text
thesevcat=re.split("- ", str(thesev))
if thesevcat is None:
thesevcat=None
else:
#looking to set thesevcat='Medium' for example
thesevcat=thesevcat[1]
sometimes thesevcat is successfully parsed the value, othertimes it cant parse it, so I want to set it to None
However, I keep getting this error:
thesevcat=thesevcat[1]
IndexError: list index out of range
what is going wrong here? Thanks
thesevcat=thesevcat[1]
IndexError: list index out of range
List index out of range is pretty explicit, it means that if thesevcat is in fact a list (which we don't really know seeing your code but I guess it is), it doesn't have a 2nd index, which means it's a list containing in maximum one element (for instance ["medium"] )
Please keep in mind that the first index of a list is 0, so if your list is your_list = ["medium"], to access "medium", you need to write your_list[0]
if you wanted to access the 2nd element of your list, then your list would need to be at least 2 element long, then you'd access it with the index 1
for instance:
your_list = ["medium", "large"]
print(your_list[1])
# would print large

Finding the middle of a list

So I am trying to find the median of the list "revenues" which will be named "base_revenue".
Comments:
#Assume that revenues always has an odd number of members
#Write code to set base_revenue = midpoint of the revenue list
#Hint: Use the int and len functions
revenues = [280.00, 382.50, 500.00, 632.50, 780.00]
{def findMiddle(revenues):
middle = float(len(revenues))/2
if middle % 2 != 0:
return revenues[int(middle - .5)]
else:
return (revenues[int(middle)], revenues[int(middle-1)])}
I'm getting invalid syntax. The median function itself works, but maybe there is a more efficient way to do it.
Hint: the answer to this is far simpler than you've made it. You can even do it in a single line, unless your instructor specifically requires you to define a function.
You're told the list will always have an odd number of items; all you need is the index of the middle item. Remember that in Python, indices start at 0. So, for instance, a list of length 5 will have its middle element at index 2. A list of length 7 will have its middle element at index 3. Notice a pattern?
Your assignment also reminds you about len(), which finds the length of something (such as a list), and int(), which turns things (if possible) into integers. Notably, it turns a floating-point number into the the closest integer at or below it (a "floor" function); for instance it turns 2.5 into 2.
Can you see how you might put those together to programmatically find the midpoint index?

Why would a list() method be used on a python list in a recursion problem?

I'm currently learning Depth-First Search in Python and a problem asked that, given a Binary Search Tree and a number N, find all paths from root-to-leaf such that the sum of all the node values of each path equals N.
I did everything right, but my code didn't work (it resulted in an empty 2D array). When looking at the solution, the only difference was "allPath.append(list(currPath))", while the code I wrote was simply 'allPath.append(currPath)'. When I made this change, the code worked perfectly Here's the full code:
def findPathSum(root, sum):
allPath = []
_findPathSum(root, sum, [], allPath)
return allPath
def _findPathSum(currNode, sum, currPath, allPath):
if currNode is None:
return
currPath.append(currNode.val)
if currNode.val == sum and currNode.left is None and currNode.right is None:
print(currPath)
allPath.append(list(currPath))
else:
_findPathSum(currNode.left, sum-currNode.val, currPath, allPath)
_findPathSum(currNode.right, sum-currNode.val, currPath, allPath)
del currPath[-1]
What I'm confused about is that currPath is already a list, and only contains integers (which are the node values). When I print currPath before it is appended to allPaths, it also correctly displays a list with integer values. Yet after I append it to allPaths, allPaths is just an empty array. However, using the list() method on it, for some reason, displays the correct 2D array with the right integer values. I have no clue why this would work.
From my understanding, the list() method simply takes an iterable and turns it into a list...however currPath was already a list. I feel like I'm missing something really obvious.
list creates a brand new list (although the elements are not brand new), a new list object. In your case, without using list you will simply be appending the exact same list object to allPath on each recursive call.
Therefore, since all the elements of allPath are the exact same list, changing that list changes all of the elements of allPath. For example, when at the end of _findPathSum you do del currPath[-1], you are effectively deleting the final element of every element of allPath. Since in the end currPath will be empty, that is what you see at the end in allPath - a list containing empty lists.

Finding the shortest word in a string

I'm new to coding and I'm working on a question that asks to find the shortest word within a sentence. I'm confused what the difference between:
def find_short(s):
for x in s.split():
return min(len(x))
and
def find_short(s):
return min(len(x) for x in s.split())
is, because the former gives me an error and the latter seems to work fine. Are they not virtually the same thing?
Are they not virtually the same thing?
No, they are not the same thing. If s equals "hello world", in the first iteration, x would be "hello". And there are two things wrong here:
You are trying to return in the very first iteration rather than going over all the elements (words) to find out what's the shortest.
min(len(x)) is like saying min(5) which is not only an bad parameter to pass to min(..) but also doesn't make sense. You'd want to pass a list of elements from which min will calculate the minimum.
The second approach is actually correct. See this answer of mine to get an idea of how to interpret it. In short, you are calculating length of every word, putting that into a list (actually a generator), and then asking min to run its minimum computation on it.
There's an easier approach to see why your second expression works. Try printing the result of the following:
print([len(x) for x in s.split()])
The function min takes an array as parameter.
On your 1st block, you have
def find_short(s):
for x in s.split():
return min(len(x))
min is called once on the length of the 1st word, so it crashes because it's expecting an array
You second block is a little different
def find_short(s):
return min(len(x) for x in s.split())
Inside min, you have len(x) for x in s.split() which will return an array of all the lengths and give it to min. Then, with this array, min will be able to return the smallest.
No, they are not the same thing.
In first piece of code you are entering for cycle and trying to calculate min of the first word's length. min(5) doesn't make sense, does it? And even if it could be calculated, return would have stopped executing this function (other words' lengths would not have been taken into consideration).
In second one, len(x) for x in s.split() is a generator expression yielding the lengths of all the words in your sentence. And min will calculate the minimal element of this sequence.
Yes, the examples given are very different.
The first example effectively says:
Take the string s, split it by spaces, and then take each word, x, found and return the minimum value of just the length of x.
The second example effectively says:
Find the minimum value in the list generated by len(x) for x in s.split().
That first example generates an error because the min function expects to compare at least 2 or more elements, and only 1 is provided.
That second example works because the list that is generated by len(x) for x in s.split() converts a string, like say "Python types with ducks?" to a list of word lengths (in my example, it would convert the string to [6, 5, 4, 6]). That list that is generated (this is also why it's called a generator), is what the min function then uses to find the minimum value inside said list.
Another way to write that first example so that it works like you would expect is like this
def find_short(s):
min_length = float("inf")
for x in s.split():
if len(x) < min_length:
min_length = len(x)
return min_length
However, notice how you have to keep track of a variable that you do not have to define using the list generator method in your second example. Although this is not a big deal when you are learning programming for the first time, it becomes a bigger deal when you start making larger, more complex programs.
Sidenote:
Any value that follows the return keyword is what a function "outputs", and thus no more code gets executed.
For example, in your first example (and assuming that the error was not generated), your loop would only ever execute once regardless of the string you give it because it does not check that you actually have found the value you want. What I mean by that is that any time your code encounters a return statement, it means that your function is done.
That is why in my example find_short function, I have an if statement to check that I have the value that I want before committing to the return statement that exits the function entirely.
There is mainly two mistakes here.
First of, seems you are returning the length of the string, not the string itself.
So your function will return 4 instead of 'book', for example.
I will get into how you can fix it in short.
But answering your question:
min() is a function that expects an iterable (entities like array).
In your first method, you are splitting the text, and calling return min(len(word)) for each word.
So, if the call was successfully, it would return on the first iteration.
But it is not successfully because min(3) throws an exception, 3 is not iterable.
On your second approach you are creating a list of parameters to min function.
So your code first resolves len(x) for x in s.split() returning something like 3,2,3,4,1,3,5 as params for min, which returns the minimum value.
If you would like to return the shortest word, you could try:
def find_short(s):
y = s.split()
y.sort(key=lambda a: len(a))
return y[0]

Quick Sort using Python

I was wondering if someone can help me to fix the error my code for quick sort has:
It does not compile and highlights the last line of the code in red.
I can not figure out what is wrong. sort is already defined as a function so why is it highlighted as red?
def sort(*myarray):
less = []
equal = []
greater = []
if len(myarray) > 1:
pivot = myarray[0]
for x in myarray:
if x < pivot:
less.append(x)
if x == pivot:
equal.append(x)
if x > pivot:
greater.append(x)
return sort(less)+sort(equal)+sort(greater)
else:
return myarray
print sort([12,4,5,6,7,3,1,15])
You're defining the function as taking a variable number of arguments (the *myarray bit), but then using myarray inside as a single argument (the list to sort), when it is a list containing the list to sort.
You probably should remove the * from your function parameter. This questions esplains it quite thoroughly.
You could keep the *, but then you would have to play a bit with tuple unpacking to get the same result.
edit
Although the above is true, this might not be the issue you're encountering.
IDLE will give you the invalid syntax error on the ast line, because in interactive mode - with lines starting with >>>, it accepts only one statement at a time. In your case that statement is the sort() definition.
Try hitting enter 2 times after the function definition, this should get you back to the repl, where you can introduce another statement (print sort([12,4,5,6,7,3,1,15]))
There are a couple things wrong which makes me curious how you are testing this:
Python code is not "compiled", it is interpreted. (Okay, not precisely true; it's parsed into a sort of byte-code; still, it's not compiled in the same sense as a language such as C, where the entire program has to be converted into machine instructions before any of it can be run.) Also you mention the last line of code is highlighted in red -- by what?
This code actually works, but only if you remote the star/asterisk in front of myarray in def sort(*myarray):. Otherwise it actually returns a single-element tuple containing the original array.
Assuming you have two or more elements that equal a pivot at some point, you get an infinite loop, because you will get: equal = [x,x] (two elements at least), and then invoke sort([x,x]), which in its turn will take x as a pivot, and create equal = [x,x], and cause sort([x,x]), ....
Simple solution to this problem: What should be the output of the sort(equal)? How do you sort a list of identical elements?
Edit: Well, your comments show that you are looking for a different problem, but I'll leave it here because it explains a different issue you have with your code and should be solved.
If it is a function for quick sorting, can you really use the function sort in it?
Wouldn't something like this work?
def qsort(list):
pivind=0
left, right, pivot= [], [], []
for x in list:
if list[pivind]==x: pivot.append(x)
elif list[pivind]>x: left.append(x)
else: right.append(x)
if len(left)>1: left=qsort(left)
if len(right)>1: right=qsort(right)
return (left + pivot + right)

Categories

Resources