Python, looping and get the first max value - python

Let's say I have this list containing these numbers: 1, 4, 8, 3, 5, 9, 2
I want to loop through this and get 8 because it's the first max value I encounter when loop through the list
I'm thinking of loop through each [i], and + the if statement:
if [i] < [i+1] and [i+1] > [i+2]:
print(i)
Although this print 8 which is what I want, it also prints 9 because it satisfied the condition. Is there a way to make it stop after printing 8?!

Below is the code you can try though to get the first max value between i and i+1 index through the list
nums = [1, 4, 8, 3, 5, 9, 2]
for i in range(len(nums)-1):
if nums[i] > nums[i+1]:
print(nums[i])
break

You can use the break statement to break out of your loop. You can check out the use of break, continue and pass statements in Python here,
https://www.geeksforgeeks.org/break-continue-and-pass-in-python/
The break statement is what is applicable to you here.
So, your code would look something like this,
for i in range(len(nums)-1):
if [i] < [i+1]:
print(i)
break

By "first max", I'm assuming you mean the point where the immediate next element is lower?
Thats what I understood also going by your example -
Want 8 as the output out of [1, 4, 8, 3, 5, 9, 2]
If that is what you're looking for, you can try this -
a = [1, 4, 8, 3, 5, 9, 2]
for idx, val in enumerate(a):
if val > a[idx+1]:
# print(f"{idx} : {val}")
print(val)
break
I'm checking for the 1st occurrence where an element is higher than its very next element and breaking out of the loop at that point.

Related

How can I move the elements in my list without getting an error?

I get an "Out of range error" everytime I run this code. I'm trying to get the value of i = 0 to i = 2 etc.
element = [x for x in range(10)]
l = len(element)
print(element)
for i in range(l):
element[i] = element[i+1]
print(element)
I would recommend starting with changing for i in range(l) to for i in range(l-1). That will ensure that the index i+1 is less than l.
The catch with this is that the last element of element won't be changed, but figuring out what to do with that element is up to you.
If I understand the problem correctly, your expected result is to change element from:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
to:
[0, 0, 1, 2, 3, 4, 5, 6, 7, 8 ]
First, your loop goes one item too far - the last value of i will be the index of the last element; so that element[i+1] does not exist. This is easy to fix:
for i in range(l-1):
but then there is another problem: element[i] = element[i+1] moves element[1] to element[0] etc., so the direction is wrong - what you want is:
element[i+1] = element[i]
And anyway, it is much easier and more efficient just to duplicate the first element:
element.insert(0, element[0])
and remove the last one:
element.pop()
If I misunderstood and your expected result is in fact:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
then
element.pop(0)
is even simpler.
You are trying to copy the last value to an index that doesn't exist yet.You have to use append for the last value.
element = [x for x in range(10)]
for i in range(len(element)):
if i == len(element):
element.append(element[i])
else:
element[i] = element[i+1]

List index out of range using While loop

This is my first time posting and I am a bit of newbie so please excuse any errors in my question. I have to create a function that uses the While loop and takes in a list of numbers and adds each number to a new list until the a specific number is reached. For example - I want each number in a list to be added until the number 5 is reached in the list. If the number 5 is not in the list, then I would get the entire list as is. The issue I am having is with this last part. My current code, posted below, can give me a new list of numbers that stops at the number 5 but I get the "List index out of range" error when the number 5 is not included in the list. I am sure its something small that I am not factoring in. Any help or guidance on what I am doing wrong would be greatly appreciated.
def sublist(x):
i = 0
num_list = []
while x[i] != 5:
num_list.append(x[i])
i = i + 1
return num_list
print(sublist([1, 2, 5, 7])) #works fine
print(sublist([1, 2, 7, 9])) #list index out of range error
As others have pointed out, it is best to use a for loop when you already know the number loops you need (e.g.: len(x) in your case).
If you still really want to use a while loop instead, you will need to check every loop to see if you have checked every item in the old list, and exit the loop if you do. Here's what your code could look like if you're using a while loop:
def sublist(x):
i = 0
num_list = []
original_length = len(x)
while i < original_length and x[i] != 5:
num_list.append(x[i])
i = i + 1
return num_list
print(sublist([1, 2, 5, 7])) #works fine
print(sublist([1, 2, 7, 9])) #now also works fine
EDIT: I originally had the check for i < original_length inside the loop, I've changed it to be inside the while condition. BUT BE CAREFUL because the check MUST come before x[i] != 5. What I mean is that using this will work:
while i < original_length and x[i] != 5:
But this will not:
while x[i] != 5 and i < original_length:
This should do the trick. If n (5 in your example) is in the list x it will take the list until that point. Else, it will take the whole list. This isn't the most pythonic option, though, probably someone knows a better way.
def sublist(x, n):
num_list=[]
if n in x:
for i in x:
while i!=n:
num_list.append(i)
else:
num_list=x
return num_list
Your loop will not stop if there is no 5 in the list, so the index i will be equal to the length of x (length of x is out of range) in the iteration when the error happens.
When looping with python, it's better to use for in loops:
def sublist(x):
num_list = []
for n in x:
if n != 5:
num_list.append(n)
else:
break
return num_list
print(sublist([1, 2, 5, 7])) # [1, 2]
print(sublist([1, 2, 7, 9])) # [1, 2, 7, 9]
Try this
def sublist(x):
x.sort()
limit_num = 5
if limit_num not in x:return x
return x[:x.index(limit_num)]
print(sublist([1, 2, 5, 7]))
print(sublist([1, 2, 7, 9]))
Result:[1, 2]
[1, 2, 7, 9]

Appending a list through if condition in python

This could be a very basic question, but I realized I am not understanding something.
When appending new things in for loop, how can I raise conditions and still append the item?
For instance:
alist = [0,1,2,3,4,5]
new = []
for n in alist:
if n == 5:
continue
else:
new.append(n+1)
print(new)
Gets me
[1, 2, 3, 4, 5]
How do I get
[1, 2, 3, 4, 5, 5] # 4 is incremented, 5 is added 'as is'
Essentially, I want to tell python to not go through n+1 when n==5.
Would this be the only solution? append n==5 separately in a list and then sum new and the separate list?
Why don't you just append the 5 instead of using continue, is there any other condition?
for n in alist:
if n == 5:
new.append(n)
else:
new.append(n+1)
You can use the fact the a boolean True is 1 while a False is 0 combined with a list comprehension like:
Code:
[x + int(i != 5) for i, x in enumerate(alist)]
Test Code:
alist = [0, 1, 2, 3, 4, 5]
new = [x + int(i != 5) for i, x in enumerate(alist)]
print(new)
Result:
[1, 2, 3, 4, 5, 5]
Seems like you didn't get the point of 'continue'. The Python keyword 'continue', means you do nothing in that if condition, so basically you tell the program "do nothing" when n == 5 and if n is not 5, you do some operation. That's why you got your original result. Hope it may help.

Why is the range loop in bubble sort reversed?

I am new to Python and learning data structure in Python. I am trying to implement a bubble sort algorithm in python and I did well but I was not getting a correct result. Then I found some tutorial and there I saw that they are first setting a base range for checking.
So the syntax of range in python is:
range([start], stop[, step])
And the bubble sort algorithm is:
def bubbleSort(alist):
for i in range(len(alist) - 1, 0, -1):
for j in range(i):
if alist[j] > alist[j+1]:
temp = alist[j]
alist[j] = alist[j+1]
alist[j+1] = temp
return alist
print(bubbleSort([5, 1, 2, 3, 9, 8, 0]))
I understood all the other logic of the algorithm but I am not able to get why the loop is starting from the end of the list and going till first element of the list:
for i in range(len(alist) - 1, 0, -1):
Why is this traversing the list in reverse? The main purpose of this loop is setting the range condition only so why can't we traverse from the first element to len(list) - 1 like this:
for i in range(0, len(alist) - 1, 1):
In your code, the index i is the largest index that the inner loop will consider when swapping the elements. The way bubble sort works is by swapping sibling elements to move the largest element to the right.
This means that after the first outer iteration (or the first full cycle of the inner loop), the largest element of your list is positioned at the far end of the list. So it’s already in its correct place and does not need to be considered again. That’s why for the next iteration, i is one less to skip the last element and only look at the items 0..len(lst)-1.
Then in the next iteration, the last two elements will be sorted correctly, so it only needs to look at the item 0..len(lst)-2, and so on.
So you want to decrement i since more and more elements at the end of the list will be already in its correct position and don’t need to be looked at any longer. You don’t have to do that; you could also just always have the inner loop go up to the very end but you don’t need to, so you can skip a few iterations by not doing it.
I asked why we are going reverse in the list like len(list)-1,0. Why are we not going forward way like 0,len(list)-1?
I was hoping that the above explanation would already cover that but let’s go into detail. Try adding a print(i, alist) at the end of the outer loop. So you get the result for every iteration of i:
>>> bubbleSort([5, 1, 3, 9, 2, 8, 0])
6 [1, 3, 5, 2, 8, 0, 9]
5 [1, 3, 2, 5, 0, 8, 9]
4 [1, 2, 3, 0, 5, 8, 9]
3 [1, 2, 0, 3, 5, 8, 9]
2 [1, 0, 2, 3, 5, 8, 9]
1 [0, 1, 2, 3, 5, 8, 9]
As you can see, the list will be sorted from the right to the left. This works well for our index i which will limit how far the inner loop will go: For i = 4 for example, we already have 3 sorted elements at the end, so the inner loop will only have to look at the first 4 elements.
Now, let’s try changing the range to go in the other direction. The loop will be for i in range(0, len(alist)). Then we get this result:
>>> bubbleSort([5, 1, 3, 9, 2, 8, 0])
0 [5, 1, 3, 9, 2, 8, 0]
1 [1, 5, 3, 9, 2, 8, 0]
2 [1, 3, 5, 9, 2, 8, 0]
3 [1, 3, 5, 9, 2, 8, 0]
4 [1, 3, 5, 2, 9, 8, 0]
5 [1, 3, 2, 5, 8, 9, 0]
6 [1, 2, 3, 5, 8, 0, 9]
As you can see, this is not sorted at all. But why? i still limits how far the inner loop will go, so at i = 1, the loop will only look at the first pair and sort that; the rest will stay the same. At i = 2, the loop will look at the first two pairs and swap those (once!); the rest will stay the same. And so on. By the time the inner loop can reach the last element (which is only on the final iteration), there aren’t enough iterations left to swap the zero (which also happens to be the smallest element) to the very left.
This is again because bubble sort works by sorting the largest elements to the rightmost side first. So we have to start the algorithm by making the inner loop be able to reach that right side completely. Only when we are certain that those elements are in the right position, we can stop going that far.
There is one way to use a incrementing outer loop: By sorting the smallest elements first. But this also means that we have to start the inner loop on the far right side to make sure that we check all elements as we look for the smallest element. So we really have to make those loops go in the opposite directions.
It's because when you bubble from the start of the list to the end, the final result is that the last item in the list will be sorted (you've bubbled the largest item to the end). As a result, you don't want to include the last item in the list when you do the next bubble (you know it's already in the right place). This means the list you need to sort gets shorter, starting at the end and going down towards the start. In this code, i is always the length of the remaining unsorted list.
You can use this for:
for i in range(0,len(alist)-1,1):
but consequently you should change your second iteration:
for j in range(0,len(alist)-i,1):
I think the purpose of using reverse iteration in the first line is to simplify the second iteration. This is the advantage of using python
as #Jeremy McGibbon's answer, the logic behind bubble sort is to avoid j reach the "sorted part" in the behind of list. When using the example code, j range will be decreased as the value of i decrease. When you change i to increasing, you should handle j iteration differently
You can write the code as follow
lst = [9,6,5,7,8,3,2,1,0,4]
lengthOfArray = len(lst) - 1
for i in range(lengthOfArray):
for j in range(lengthOfArray - i):
if lst[j] > lst[j + 1]:
lst[j], lst[j + 1] = lst[j + 1], lst[j]
print(lst)

Get previous value based in specific item

I am trying a script where we use a list item and then I will get the previous item.
lst = [1, 3, 4, 6, 8, 10]
next_item = next((x for x in lst if x > 6), None)
print next_item #8
This code works correctly for the item after 6. However i need the item before 6.
I am looking in docs for a prev method but i can't find anything related.
Any idea about that?
Assuming by "before" you mean "previous in lst", it is not necessary to use such a complicated way. This
lst[lst.index(6) - 1]
will give
4
while this
lst[lst.index(6) + 1]
will give
8
Of course you should check for index out of bound errors.
You can loop over the reversed list with a reverse condition :
>>> next((i for i in lst[::-1] if i<6),None)
4
If you are looking for the first number larger than 6 in lst, this is one way to do it:
lst = [1, 3, 4, 6, 8, 10]
lst2 =[]
for num in lst:
if num > 6:
lst2.append(num)
lst2.sort()
print lst2[0]
The output is 8

Categories