繁体   English   中英

比较数字是否在python范围列表中的快速方法

[英]fast way to compare whether the number is in the list of ranges in python

我需要将数字列表与范围列表进行比较,看看该数字是否在范围内。

例:

list1 = [23,100,1,50,60,73]
list2 = [[0-10],[25-35],[100-110],[75-85]]

因此,我需要迭代list1并将此数字与范围列表进行比较,看看该数字是否落在任何范围内,如果是,我将增加该范围的计数器。

两个列表都非常大(100k到几百万甚至更多),并且数量是随机的。

那么解决这个问题的最佳方法是什么?

编辑-列表的格式可以是[low,high,counter]之类的列表。 上面的示例是数据示例,并没有真正遵循Python代码语法。 这两个列表都将是巨大的。

另外数字是int。

谢谢。

一种简单的方法是使第二个列表具有元组(或两个元素的列表)形式,然后使用any

list1 = [23,100,1,50,60,73]
list2 = [(0,10), (25,35), (100,110), (75,85)]

[any(y[0] <= x <= y[1] for y in list2) for x in list1]

timeit给出:

100000 loops, best of 3: 4.17 us per loop

现在,我假设您的范围是包含在内的,即内部包含85和25。 如果list1中的数字是整数,并且list2是静态的(并且也仅包含int,并且范围是非重叠的 ),则将其展平,将其排序并按0.5移边界以消除边框大小写,那么您可以使用高效的bisect O(log(N))算法:

list2 = [(0,10),(25,35),(100,110),(75,85)]
list2 = [x for tup in list2 for x in tup]
list2.sort()
list2 = [l - 0.5 + i%2 for i,l in enumerate(list2)]
timeit [bisect_left(list2, x)%2 == 1 for x in list1]
100000 loops, best of 3: 1.64 us per loop

这是一种不太易读的设计,因为您有一堆数字,没有明显的指示,左边的边界在右边,但是它更快,更可扩展。 如果list1的数字进入带有偶数索引的位置,则它在范围之间,否则在内部。


它仍然比简单地将所有数字存储在set中并使用in慢(这仅在list1中的数字都是int时才有效):

list3 = set(range(0,11) + range(25,36) + range(100,111) + range(75,86))
[x in list3 for x in list1]

这使:

1000000 loops, best of 3: 376 ns per loop

该解决方案可能对您不可行,因为如果您的第二个列表确实很大,那么它甚至可能无法容纳在内存中。

暂无
暂无

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

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