cutteeth
cutteeth

Reputation: 2213

Get the immediate minimum among a list of numbers in python

How can I get the next minimum value to a value provided in python? Is there any inbuilt functions for it?

>>>num_list=[1,2,3,4]
>>> min(num_list)
1
>>> max(num_list)
4

How can I find the next lowest to 3 or next greatest to 2 ? The expected results are 2 and 3 respectievely.

Upvotes: 8

Views: 8134

Answers (7)

gboffi
gboffi

Reputation: 25023

TL;DR Either min(n for n in my_list if n>lower_bound) or max(n for n in my_list if n<upper_bound)


A much faster alternative for finding the immediate minimum or the immediate maximum is numpy

>>> import numpy as np
>>> np.random.seed(10)
>>> a = np.random.random(10000)
>>> a[a>0.7].min()
0.69999533217645671
>>> a[a<0.7].max()
0.70003449227846715

If you are uncomfortable using the numpy machinery and want to deal simply with a list

>>> a = list(a)

then you can use the min and max builtins along with generator expressions

>>> min(n for n in a if n>0.7)
0.69999533217645671
>>> max(n for n in a if n<0.7)
0.70003449227846715
>>>

Using lists you have, of course, the same results but beware that there is a difference in performance: using ipython and %timeit to get the timings, I had 871 µs using numpy and 13.8 ms using regular lists for the 100000 elements array/list of the previous examples.

HTH, ciao


Post Scriptum

The solutions in my answer are all O(n), compared with the O(n log n) of methods that use sorting --- further, for large data sets the numpy approach should (italics because I have no testing at hand...) be affected by a small multiplicative factor.

Upvotes: 6

Veedrac
Veedrac

Reputation: 60137

Use heapq.nlargest and heapq.nsmallest

import heapq

num_list = [1, 2, 3, 4]

heapq.nlargest(2, num_list)
heapq.nsmallest(2, num_list)
#>>> [4, 3]
#>>> [1, 2]

Upvotes: 2

kvorobiev
kvorobiev

Reputation: 5070

You could use following approach:

num_list = [1,2,3,4]   
inds = sorted(range(len(num_list)), key=lambda k: num_list[k])

Then, inds[1] will contain index of next lowest element and so on. Also, you could use the following code without sorting:

minv = min(num_list)    
nmin = min(nm for nm in num_list if nm > minv)
maxv = max(num_list)
nmax = max(nm for nm in num_list if nm < maxv)

Upvotes: 0

Kasravnd
Kasravnd

Reputation: 107287

You can use sorted :

>>> l=sorted(num_list,reverse=True)
>>> l[l.index(3)+1]
2

But as a more pythonic way as Frerich Raabe says in comment you dont need to sore whole of list you can find the max value on elements that are lower than 3 :

>>> max(i for i in num_list if i<3)
2

And for next largest after 2 you can use min :

>>> min(i for i in num_list if i>2)
3

Upvotes: 1

Juan Lopes
Juan Lopes

Reputation: 10565

I see your question is tagged [lower-bound] and [upperbound]. If your list is sorted, Python has an equivalent of C++ <algorithm>'s lower_bound and upper_bound. They're in the bisect module. They return the indices of the begin and immediately after the end of a range of some specific value.

In [1]: import bisect

In [2]: A = [0, 1, 3, 3, 5]

In [3]: A[bisect.bisect_left(A, 3)-1]
Out[3]: 1

In [4]: A[bisect.bisect_right(A, 3)]
Out[4]: 5

Upvotes: 5

user890167
user890167

Reputation:

The provided answers are good, but if I could make a suggestion -- if there are ever times when the values could be repeated, such as

num_list = [2, 2, 4, 4, 6, 7, 8, 9]

...and so on, just sorting the list and getting the first index may not be what you're looking for.

By passing it through a set() first, you'll make sure that each entry is a singleton:

def sorted_ordered_list(sequence):
    return sorted(list(set(sequence)))

Then you can just index the returned list for whichever value you're looking for, from the lowest at index 0 to the highest.

Example:

>>> my_list = [1, 5, 4, 3, 6, 3, 8, 3, 6, 7, 4, 2, 6, 7, 9, 8, 8]
>>> sorted_ordered_list(my_list)
[1, 2, 3, 4, 5, 6, 7, 8, 9] # now index the list for the desired value
>>> 

Upvotes: 0

Ofir
Ofir

Reputation: 1855

next lowest to 3:

max([x for x in num_list if x < 3])

next greatest to 2:

min([x for x in num_list if x > 2])

Upvotes: 3

Related Questions