Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 添加范围以计算重叠_Python_Performance_Range - Fatal编程技术网

Python 添加范围以计算重叠

Python 添加范围以计算重叠,python,performance,range,Python,Performance,Range,我有一个范围列表。我现在想计算一个字典key:value,其中key是数字,value是数字存在的范围 一个不好的计算方法是: from collections import defaultdict my_dict = defaultdict(int) ranges = [range(-4200,4200), range(-420,420), range(-42,42), range(8,9), range(9,9), range(9,10)] for singleRange in range

我有一个范围列表。我现在想计算一个字典key:value,其中key是数字,value是数字存在的范围

一个不好的计算方法是:

from collections import defaultdict
my_dict = defaultdict(int)
ranges = [range(-4200,4200), range(-420,420), range(-42,42), range(8,9), range(9,9), range(9,10)]

for singleRange in ranges:
    for number in singleRange:
        my_dict[number] += 1
sort_dict = sorted(my_dict.items(), key=lambda x: x[1], reverse=True)
print(sort_dict)

您将如何更有效地执行此操作?

可能可以执行更有效的操作,但此解决方案的优点是严重依赖于
numpy
的速度。对于10k范围,这在我的笔记本电脑上运行约600毫秒

从集合导入defaultdict
将numpy作为np导入
#生成数据
def生成_范围(n):
边界=np.random.randint(-10_000,10_000,size=(n,2))
边界。排序(轴=1)
返回[边界中x,y的范围(x,y)]
范围=生成范围(10个)
#提取边界
开始,停止=np.array([[range.start,range.stop]表示范围内的范围]).T
#我们应该测试的所有数字的集合
n=np.arange(start.min(),stops.max()+1)[:,无]
#测试这些数字
计数=((n>=开始[None,:])和(n<停止[None,:])。总和(轴=1)
#把结果写进口述
d=defaultdict(int,dict(zip(n.flatte(),counts)))

改进了我之前的答案,该算法解决了
O(n+m)
中的问题,其中
n
是总范围的长度,
m
是子范围的数量

基本思想是只遍历
n
数字一次,保留当前数字所属范围的计数器。在每一步中,我们检查是否通过了范围起始,在这种情况下,计数器将递增。相反,如果我们已经通过了一个范围停止,计数器就会递减

下面的实际实现将
numpy
pandas
用于所有繁重的工作,因此该算法的迭代性质似乎不清楚,但它基本上只是我所描述的向量化版本

与我之前回答的600毫秒相比,我的笔记本电脑上10k范围的时间减少到了20毫秒。此外,这里的内存使用量也是
O(n+m)
,而那里的内存使用量是
O(nm)
,因此更大的
n
m
成为可能。您可能应该使用此解决方案,而不是第一个版本

从集合导入defaultdict
将numpy作为np导入
作为pd进口熊猫
#生成数据
def生成_范围(n):
边界=np.random.randint(-10_000,10_000,size=(n,2))
边界。排序(轴=1)
返回[边界中x,y的范围(x,y)]
范围=生成范围(10个)
#提取边界
边界=np.array([[range.start,range.stop]表示范围内的范围])
#为范围开始添加+1偏移,为范围停止添加-1偏移
偏移量=np.数组([1,-1])[None,:]。重复(边界.形状[0],轴=0)
边界=np。堆栈([边界,偏移],轴=-1)
边界=边界。重塑(-1,2)
#计算范围边界每个交叉点的范围计数
df=pd.DataFrame(边界、列=[“n”、“偏移量”])
df=df.sort_值(“n”)
df[“count”]=df[“offset”].cumsum()
df=df.groupby(“n”)[“count”].max()
#通过连接和填充NaN扩展到所有整数
索引=pd.RangeIndex(测向索引[0],测向索引[-1]+1)
df=pd.DataFrame(index=index).join(df).fillna(method=“ffill”)
#最后将结果包装在defaultdict中
d=defaultdict(int,df[“count”].astype(int).to_dict())

如果您从确定总范围(范围的最大包含范围)开始,那么您可以在该范围内迭代一次。您仍然需要进行比较,以查看总范围中的每个数字所处的子范围,因此无论哪种方式,它都会变成一个嵌套的for循环。我不认为你能在比
O(nm)
更好的情况下可靠地做到这一点,其中
n
是总范围的长度,
m
是子范围的数量。公平地说,这没那么糟糕。如果我不使用范围,有没有更好的方法?我也在考虑您描述的方法,但我认为在范围内检查x或多或少是相同的。但它可能只是检查是否低