python - 使用 Cython 循环?或更好的方法来删除落入给定范围内的元素
问题描述
我基本上是在寻找一种更快/更好/有效的方式来执行我的一段 python 代码。
这是我的部分代码的更简单版本。
import numpy as np
A = np.random.choice(100,80) # randomly select integers
A = np.sort(A) # sort it
B = np.unique(A) # drop the duplicate values
我想用这个向量 B 做的是从前一个值中删除它在给定范围内的元素。例如,如果我有一个排序的向量B = [1,2,5,7,8,11,20,25,30]
并且我想分配的范围值为 10,那么我的代码应该输出C = [1,11,25]
. (2,5,7,8 被删除,因为它与元素 1 的距离小于 10。下一个元素是 11。20 被删除,因为 20 与元素 11 的距离小于 10。下一个是 25,所以 30 是删除)。你明白了。
我写的代码如下:
def RemoveViolations(vec, L):
S = []
P = 0 # pointer
C = 0 # counter
while C < vec.size:
S.append(vec[C])
preC = np.where(vec>S[P]+L)[0]
if preC.size:
C = preC[0]
else:
C = vec.size+1
P = P+1
return np.asarray(S)
所以,现在,我可以做到这一点C = RemoveViolations(B,10)
,这就像一个魅力。
现在,问题是这是 python 中非常慢的代码。我喜欢一个大小为 100 万的排序向量,完成这段代码需要一些时间。有没有更好的方法来完成这项任务?
如果我需要实现 Cython,我将如何更改代码以在 C++ 环境中工作?我听说这并不复杂,但快速搜索效果不佳。
谢谢!
解决方案
0.15s
您的算法的复杂性是问题所在:这是在我 8 岁的笔记本电脑上执行的纯 Python 解决方案(您的实现需要 200 秒;对于 n=1000000,i/ea 提高了 1300 倍):
import random
def get_filtered_values(dist, seq):
prev_val = seq[0]
compare_to = prev_val + dist
filtered = [prev_val]
for elt in seq[1:]:
if elt <= compare_to: # <-- change to `<` to match desired results;
# this matches the results of your implementation
continue
else:
compare_to = elt + dist
filtered.append(elt)
return filtered
B = [1,2,5,7,8,11,20,25,30]
print(get_filtered_values(10, B))
n = 1000000
C = sorted(list(set([random.randint(0, n) for _ in range(n)])))
get_filtered_values(10, C)
您可以对这段代码进行cythonize,或者根据需要对其进行numpyize,但这可能不是必需的。
推荐阅读
- mysql - 我正在尝试使用 sql 将数据添加到现有行中的列
- python - 在列表/数组中发现一系列真值的最准确方法,忽略唯一的真值
- python - Tweepy 库错误 AttributeError:“元组”对象没有属性“set_access_token”
- testing - 如何在测试计划之间克隆测试用例?
- nginx - nginx 配置以启用具有源匹配的 CORS
- asp.net - Asp.net Forms Authentication with Token and RefreshToken问题
- android - AAR 是否支持默认清单合并?
- python - 使用 Python 的 PLAXIS API
- daml - 如何在 DAML 的列表中找到特定元素的索引?
- facebook - 从活跃的 Facebook 广告中获取评论