Python在列表或数组中查找范围之间的数字
Posted
技术标签:
【中文标题】Python在列表或数组中查找范围之间的数字【英文标题】:Python find numbers between range in list or array 【发布时间】:2018-04-09 08:26:53 【问题描述】:我有一个包含数百万个数字的列表,这些数字总是增加到最后,我需要在指定范围内查找并返回数字,例如大于 X 但小于 Y 的数字,列表中的数字可以更改,我正在搜索的值也会更改
我一直在使用这种方法,请注意这是一个基本示例,数字不统一或与我的程序中显示的相同
l = [i for i in range(2000000)]
nums = []
for element in l:
if element > 950004:
break
if element > 950000:
nums.append(element)
#[950001, 950002, 950003, 950004]
虽然速度很快,但对于我的程序正在执行的操作,我有点需要它更快一点,数字变化很大,所以我想知道是否有更好的方法来使用 pandas 系列或 numpy 数组来做到这一点?但到目前为止,我所做的只是在 numpy 中做了一个示例:
a = numpy.array(l,dtype=numpy.int64)
熊猫系列会更实用吗?使用查询()?使用数组而不是 python 对象的 python 列表来解决这个问题的最佳方法是什么
【问题讨论】:
您是否尝试将列表过滤为一组值之间的数字? 不,抱歉,返回 x 和 y 之间的值 您似乎只是想从950000
到950004
中提取一个切片。有什么意义?
也许,用二分法搜索范围边界的索引会更快。
您能否更新您的示例以更接近您的实际问题?
【参考方案1】:
这是一个使用二分搜索的解决方案。你说的是数以百万计的数字。从技术上讲,二分搜索将通过将运行时复杂度降低到 O(log n) 来使算法更快,而忽略最后的切片步骤。
import bisect
l = [i for i in range(2000000)]
lower_bound = 950000
upper_bound = 950004
lower_bound_i = bisect.bisect_left(l, lower_bound)
upper_bound_i = bisect.bisect_right(l, upper_bound, lo=lower_bound_i)
nums = l[lower_bound_i:upper_bound_i]
【讨论】:
不知何故它比 numpy 布尔切片 O_o 快一点; 谢谢,我可能在浏览文档时找不到这个解决方案 在bisect.bisect_right
中使用lo=lower_bound_i
参数可以提高效率。
@new_to_coding 这个列表切片,你的意思是?是的,一个布尔切片创建一个与当前数组大小相同的整个布尔数组。 Python list-slice 非常快速和高效,用 C 实现。【参考方案2】:
以下是二分查找的两种实现(基于来自here 的代码)——一种搜索上限,另一种搜索下限。这对你更有效吗?
def binary_search_upper(seq, limit):
min = 0
max = len(seq) - 1
while True:
if max < min:
return -1
m = (min + max) / 2
if m == (len(seq) -1) or (seq[m] <= limit and seq[m+1] > limit):
return m
elif seq[m] < limit:
min = m+1
else:
max = m - 1
def binary_search_lower(seq, limit):
min = 0
max = len(seq) - 1
while True:
if max < min:
return -1
m = (min + max) / 2
if m == 0 or (seq[m] >= limit and seq[m-1] < limit):
return m
elif seq[m] < limit:
min = m+1
else:
max = m - 1
l = [i for i in range(2000000)]
print binary_search_upper(l, 950004)
print binary_search_lower(l, 950000)
【讨论】:
你为什么要使用这个已有 14 年历史的配方,而不是标准库实现(它将有很多、很多更好的常数因子)?跨度> JFTR,这比bisect
慢十倍左右。
@ekhumoro 很有趣,我在哪里可以了解更多关于 bisect
为何如此之快的信息?
@MaorVeitsman。 source code for the module 显示的是纯 python 实现,但 real implementation 是用 C 编写的。
@MaorVeitsman。 PS:纯python bisect 实现的速度大约是你的两倍:P【参考方案3】:
您可以使用 numpy 通过布尔切片获取列表的子集。
import numpy as np
a = np.arange(2000000)
nums = a[(950000<a) & (a<=950004)]
nums
# returns
array([950001, 950002, 950003, 950004])
【讨论】:
我的程序中的数字不一样,这是一个基本的例子,对不起 这个取整个数组中的所有数字,碰到停止条件后不退出。以上是关于Python在列表或数组中查找范围之间的数字的主要内容,如果未能解决你的问题,请参考以下文章