简体   繁体   English

列表中最小的 n 个数字

[英]Smallest n numbers from a list

If I have a list list1=[1,15,9,3,6,21,10,11] how do I obtain the smallest 2 integers from that?如果我有一个列表list1=[1,15,9,3,6,21,10,11]我如何从中获得最小的 2 个整数?

min() gives me one number, but what about 2? min()给了我一个数字,但是 2 呢?

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):或者,删除最小值并找到下一个最小值(对于大型数据集,这应该是最快的解决方案,因为它最多需要 3 次通过):

list1=[1,15,9,3,6,21,10,11]
m1 = min(list1)
list1.remove(m1)
m2 = min(list1)
print m1, m2 # 1 3

You can import heapq你可以导入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] .这样做的限制是,如果你有一个重复的值,比如说l=[1,3,5,1] ,两个最小值将是[1,1]

Edit 1:编辑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:编辑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感谢 Padraic Cunningham, heapq在更大的集合中更快

Using min and two passes over list1:使用 min 和两次遍历 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.list1=[1,1,9,3,6,21,10,11]其中最小的是一个骗子,他仍然会返回1,3而 nsmallest 会返回1,1所以这是需要注意的事情。

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 :这将比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

you want the n first or 2 first?你想先 n 还是先 2? this is one way to get the 2 first lowest numbers in a list:这是获取列表中前 2 个最低数字的一种方法:

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.如果有相关的重复,这将多次返回相同的数字。

If your list can't contain duplicates, you could use heapq:如果您的列表不能包含重复项,您可以使用 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]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM