find the second largest number in the given list [duplicant] - python

b=list(map(int,input().split()))
c=max(b)
for i in b:
if i == c:
b.remove(i)
else:
continue
print(max(b))
where I am getting wrong with this code I am not getting correct output for input 6 4 5 6 6

We can use a set and sorted() to grab the second highest number in the list.
Passing your list to a set will only include unique numbers
We then sort the set and grab the second last element in the list
data = [6, 4, 5, 6, 6]
sorted(set(data))[-2]
#5

First Approach
In this code, we are sorting the list b and then printing the second-last value using indexing
b=list(map(int,input().split()))
sorted(b)
print(b[-2])
Output:
6
Second Approach
In this approach, we are sorting the list, converting it to a set to remove duplicate values, converting the set again into a list and getting the second-last value
b=list(map(int,input().split()))
sorted(b)
final_b = list(set(b))
print(final_b[-2])
Output
5
Actually, the above codes can be written in a single line / fewer lines but it won't be easy for you to read if you are a beginner.

b = list(set(map(int, input().split())))
b.sort()
print(None if len(b) < 2 else b[-2])
set is used to delete duplicate values, and finally to determine if there are two numbers.

A different approach would be to use the nlargest method of the heapq module. it can be used to find the first n largest numbers
import heapq
data = [6, 4, 5, 6, 6]
heapq.nlargest(2, set(data)) # returns [6, 5]
# So we can unpack the values as below
_, second_max = heapq.nlargest(2, set(data)) # the '_' means we dont care about storing that variable
# Now print it
print(second_max) # Output: 5

Related

Loop through list to extract specific patterns

I have a quite specific question that I'm unsure about how to go forward with.
I have a list of numbers and I want to extract some specific patterns from them where I loop through the list and create a new one, it's easier to explain with an example.
Say I have a list, a = [2, 9, 3, 2, 3, 5, 7, 9].
What I want to do with this list is loop through 4 numbers at a time and give them corresponding letters, depending on when they occur in the sequence.
i.e. First four numbers = 2932 = ABCA
Second sequence of numbers = 9323 = ABCB
Third sequence = 3235 = ABAC
Fourth sequence = 2357 = ABCD
Fifth sequence = 3579 = ABCD
I then want to take these sequences and add them to another list which would now look like,
b = [ABCA, ABCB, ABAC, ABCD, ABCD]
I'm really unsure about how the format of the code should be, the length of the new list will always be 3 less than the original. Any help would be great, thanks.
You can use a dictionary to assign letters to numbers and read that dictionary again to access the relevant letters. It has 2 loops, which is not ideal but it does the job:
a = [2, 9, 3, 2, 3, 5, 7, 9]
len_a = len(a)
output = []
letters = 'ABCD'
for i in range(len_a-3):
d = {}
k = 0
for j in a[i:i+4]:
if j not in d:
d[j] = letters[k]
k += 1
else:
continue
letter_assignment = ''.join([d[j] for j in a[i:i+4]])
output.append(letter_assignment)
Output:
print(output)
# ['ABCA', 'ABCB', 'ABAC', 'ABCD', 'ABCD']
I recommend using zip function for corresponding the numbers with the letters, while for the loop, use the "for" function.

Find index of minimum value in a Python sublist - min() returns index of minimum value in list

I've been working on implementing common sorting algorithms into Python, and whilst working on selection sort I ran into a problem finding the minimum value of a sublist and swapping it with the first value of the sublist, which from my testing appears to be due to a problem with how I am using min() in my program.
Here is my code:
def selection_sort(li):
for i in range(0, len(li)):
a, b = i, li.index(min(li[i:]))
li[a], li[b] = li[b], li[a]
This works fine for lists that have zero duplicate elements within them:
>>> selection_sort([9,8,7,6,5,4,3,2,1])
[1, 2, 3, 4, 5, 6, 7, 8, 9]
However, it completely fails when there are duplicate elements within the list.
>>> selection_sort([9,8,8,7,6,6,5,5,5,4,2,1,1])
[8, 8, 7, 6, 6, 5, 5, 5, 4, 2, 9, 1, 1]
I tried to solve this problem by examining what min() is doing on line 3 of my code, and found that min() returns the index value of the smallest element inside the sublist as intended, but the index is of the element within the larger list rather than of the sublist, which I hope this experimentation helps to illustrate more clearly:
>>> a = [1,2,1,1,2]
>>> min(a)
1 # expected
>>> a.index(min(a))
0 # also expected
>>> a.index(min(a[1:]))
0 # should be 1?
I'm not sure what is causing this behaviour; it could be possible to copy li[i:] into a temporary variable b and then do b.index(min(b)), but copying li[i:] into b for each loop might require a lot of memory, and selection sort is an in-place algorithm so I am uncertain as to whether this approach is ideal.
You're not quite getting the concept correctly!
li.index(item) will return the first appearance of that item in the list li.
What you should do instead is if you're finding the minimum element in the sublist, search for that element in the sublist as well instead of searching it in the whole list. Also when searching in the sliced list, you will get the index in respect to the sublist. Though you can easily fix that by adding the starting step to the index returned.
A small fix for your problem would be:
def selection_sort(li):
for i in range(0, len(li)):
a, b = i, i + li[i:].index(min(li[i:]))
li[a], li[b] = li[b], li[a]
When you write a.index(min(a[1:])) you are searching for the first occurence of the min of a[1:], but you are searching in the original list. That's why you get 0 as a result.
By the way, the function you are looking for is generally called argmin. It is not contained in pure python, but numpy module has it.
One way you can do it is using list comprehension:
idxs = [i for i, val in enumerate(a) if val == min(a)]
Or even better, write your own code, which is faster asymptotically:
idxs = []
minval = None
for i, val in enumerate(a):
if minval is None or minval > val:
idxs = [i]
minval = val
elif minval == val:
idxs.append(i)

python pop() giving unexpected results [duplicate]

I was practicing python 'list variable' with 'for loop', but was surprised to see that the order of the items in the list changed.
xlist=[1,2,3,4,5]
print(xlist)
#loop all items in the lxist
for item in xlist:
print(item)
#multiply each item by 5
xlist[xlist.index(item)] = item * 5
#print the list
print(xlist)
I was expecting the list order to be [5,10,15,20,25] but instead i got [25, 10, 15, 20, 5]
I am using python 3.8(32 version) using pycharm IDE.
Can anyone clarify why the order of the list has changed
You are not using the .index method correctly. Two problems, semantically, it doesn't mean what you think it means, it gives you the first index of some object in a list. So note, on your last iteration:
xlist.index(5) == 0
Because on your first iteration, you set:
xlist[0] = 1 * 5
The correct way to do this is to maintain and index as you iterate, either manually by using something like index = 0 outside the loop and incrementing it, or by iterating over a range and extracting the item using that index. But the pythonic way to do this is to use enumerate, which automatically provides a counter when you loop:
for index, item in enumerate(xlist):
xlist[index] = item*5
The other problem is even if your items were all unique and the index returned was correct, using .index in a loop is unnecessarily making your algorithm quadratic time, since .index takes linear time.
The index method returns the index of the first occurrence of the item you have passed as an argument (assuming it exists). So, by the time you reach the last element, i.e. 5 at index 4, the item at index 0 is also 5, so you get 5 * 5 at index 0 in the final result.
When the index method is searching for the 5th number (5) it locates the first index that has that value. At this point in time, index 0 (the 1st number) is also 5 so it multiplies index 0 by 5. A better way to loop through is to use the enumerate method to loop through each index and modify the number at that index, rather than find the index afterwards. This eliminates the troubles with the index method.
xlist=[1,2,3,4,5]
print(xlist)
#loop all items in the lxist
for i, item in enumerate(xlist):
print(item)
#multiply each item by 5
xlist[i] *= 5
#print the list
print(xlist)
Results:
[1, 2, 3, 4, 5]
1
[5, 2, 3, 4, 5]
2
[5, 10, 3, 4, 5]
3
[5, 10, 15, 4, 5]
4
[5, 10, 15, 20, 5]
5
[5, 10, 15, 20, 25]

How to get the list with the highest last value in a list of lists [duplicate]

This question already has answers here:
Finding a list in a list of lists with the max value by given index and returning its first value
(2 answers)
Closed 4 years ago.
I'm trying to get the list which has the highest value in a list of lists. I have something like this:
Lists = [[0,7,6,8],[1,4,6,5], [12,1,8,3]]
And I want to retrieve the list that has the highest last value, first list in this case. How should I go about this?
Use max with a key:
max(Lists, key=lambda x: x[-1])
>>> [0, 7, 6, 8]
Using max() + operator.itemgetter():
from operator import itemgetter
Lists = [[0,7,6,8], [1,4,6,5], [12,1,8,3]]
print(max(Lists, key=itemgetter(-1)))
# [0, 7, 6, 8]
How the above works:
itemgetter(-1) fetches the last item, and applies it the key argument of max(), which indicates the max must be found by comparing the last element of every sublist.
A side note, max() is always O(N), since you need to check every element of the list to determine the maximal element.
Other option:
array = [[0,7,6,8],[1,4,6,5], [12,1,8,3]]
max_i, max_e = 0, array[0][-1]
for i, e in enumerate(array):
if e[-1] > max_e: max_i, max_e = i, e[-1]
array[max_i]
#=> [0, 7, 6, 8]

How to delete the lowest number in an array, and if there's several minimum numbers, delete the first

I'm trying to make a script, where the input is an array with random numbers. I try to delete the lowest number in the array which is no problem. But if there are several occurrences of this number in the array, how do I make sure that it is only the first occurrence of this number that gets deleted?
Let's say we have the following array:
a = np.array([2,6,2,1,6,1,9])
Here the lowest number is 1, but since it occurs two times, I only want to remove the first occurence so i get the following array as a result:
a = np.array([2,6,2,6,1,9])
Since you're using NumPy, not native Python lists:
a = np.array([2,6,2,1,6,1,9])
a = np.delete(a, a.argmin())
print(a)
# [2 6 2 6 1 9]
np.delete: Return a new array with sub-arrays along an axis deleted.
np.argmin: Returns the indices of the minimum values along an axis.
With a NumPy array, you cannot delete elemensts with del as you can in a list.
A simple way to do this with a native Python list is:
>> a = [1,2,3,4,1,2,1]
>> del a[a.index(min(a))]
>> a
[2, 3, 4, 1, 2, 1]
You can simple do two things first sort and then shift array. For example
var list = [2, 1, 4, 5, 1];
list=list.sort(); // result would be like this [1,1,2,4,5]
list=list.shift();// result would be [1,2,4,5]

Categories