Reputation:
If I have a list list1=[1,15,9,3,6,21,10,11]
how do I obtain the smallest 2 integers from that?
min()
gives me one number, but what about 2?
Upvotes: 4
Views: 3508
Reputation: 180391
Using min and two passes over list1:
list1=[1,15,9,3,6,21,10,11]
mn = min(list1)
mn2 = min(i for i in list1 if i != mn)
print((mn,mn2))
(1, 3)
It list1=[1,1,9,3,6,21,10,11]
where the smallest was a dupe, his would still return 1,3
where nsmallest would return 1,1
so that is something to be aware of.
You can also do it in one pass over the list since you have no dupes:
def min_two(lst):
mn1, mn2 = float("inf"),float("inf")
for ele in lst:
if ele < mn1:
mn1 = ele
continue
if ele < mn2:
mn2 = ele
return mn1, mn2
Which will be faster than a heapq.nsmallest
:
In [34]:list1=[random.random() for j in range(10**5)]
In [35]: timeit heapq.nsmallest(2,list1)
100 loops, best of 3: 11.6 ms per loop
In [36]: timeit min_two(list1)
100 loops, best of 3: 9.01 ms per loop
In [37]: %timeit sorted(list1)[:2]
10 loops, best of 3: 42.2 ms per l
And if you did actually want to handle dupes:
def min_two_dupes(lst):
mn1, mn2 = float("inf"),float("inf")
for ele in lst:
if ele < mn1:
mn1 = ele
continue
if ele < mn2 and ele != mn1:
mn2 = ele
return mn1, mn2
Which will get the two lowest numbers ignoring repeats:
In [48]: list1 = [12, 15, 3, 3, 6, 21, 10, 11]
In [49]: min_two_dupes(list1)
Out[49]: (3, 6)
And runs just as efficiently:
In [52]: timeit min_two_dupes(list1)
100 loops, best of 3: 9.04 ms per loop
Upvotes: 1
Reputation: 1987
you want the n first or 2 first? this is one way to get the 2 first lowest numbers in a list:
list1=[1,15,9,3,6,21,10,11]
list1.sort()
twoFirst = list1[:2]
nFirst = list1[:n]
I am probably deleting my answer as someone suggested while I was writing my answer. This was return the same number multiple times if there are relevant duplicates.
Upvotes: 1
Reputation: 53525
You can sort the list and grab the first two elements:
sorted(list1)[:2]
Or, remove the min and find the next min (which should be the quickest solution for large datasets because it requires 3 passes at most):
list1=[1,15,9,3,6,21,10,11]
m1 = min(list1)
list1.remove(m1)
m2 = min(list1)
print m1, m2 # 1 3
Upvotes: 4
Reputation: 15953
You can import heapq
import heapq
list1=[1,15,9,3,6,21,10,11]
print(heapq.nsmallest(2,list1))
The limitation with that is if you have a repeated value let's say l=[1,3,5,1]
, the two smallest values will be [1,1]
.
Edit 1:
In [2]:
list1=[1,15,9,3,6,21,10,11]
In [3]:
%timeit sorted(list1)[:2]
1000000 loops, best of 3: 1.58 µs per loop
In [5]:
import heapq
%timeit heapq.nsmallest(2,list1)
100000 loops, best of 3: 4.18 µs per loop
From the two, it seems sorting the list is faster for smaller sets.
Edit 2:
In [14]:
import random
list1=[[random.random() for i in range(100)] for j in range(100)]
In [15]:
%timeit sorted(list1)[:2]
10000 loops, best of 3: 55.6 µs per loop
In [16]:
import heapq
%timeit heapq.nsmallest(2,list1)
10000 loops, best of 3: 27.7 µs per loop
Thanks to Padraic Cunningham, heapq
is faster with larger sets
Upvotes: 3
Reputation: 311018
If your list can't contain duplicates, you could use heapq:
from heapq import nsmallest
list1=[1,15,9,3,6,21,10,11]
smallest = nsmallest(2, list1)
If it can, you could sort the list and then slice it:
smallest = sorted(list1)[0:2]
Upvotes: 0