Python 有什么简单的方法可以将丢失的数字序列转换为它的范围吗?
假设我有一个如下列表: ''' [1,2,3,4,9,10,11,20] ''' 我需要的结果是: ''' [[4,9],[11,20]] ''' 我定义了一个如下的函数:Python 有什么简单的方法可以将丢失的数字序列转换为它的范围吗?,python,Python,假设我有一个如下列表: ''' [1,2,3,4,9,10,11,20] ''' 我需要的结果是: ''' [[4,9],[11,20]] ''' 我定义了一个如下的函数: def get_range(lst): i=0 seqrange=[] for new in lst: a=[] start=new end=new if i==0: i=1 old=new else: if new - old >
def get_range(lst):
i=0
seqrange=[]
for new in lst:
a=[]
start=new
end=new
if i==0:
i=1
old=new
else:
if new - old >1:
a.append(old)
a.append(new)
old=new
if len(a):
seqrange.append(a)
return seqrange
还有其他更简单有效的方法吗?我需要在数百万的范围内执行此操作。我认为解决方案没有任何低效之处,但您可以对代码进行大量清理:
seqrange = []
for i in range(len(lst)-1):
if lst[i+1] - lst[i] > 1:
seqrange.append([lst[i], lst[i+1]])
有一种基于迭代器的解决方案。允许逐个获取间隔:
flist = [1,2,3,4,9,10,11,20]
def get_range(lst):
start_idx = lst[0]
for current_idx in flist[1:]:
if current_idx > start_idx+1:
yield [start_idx, current_idx]
start_idx = current_idx
for inverval in get_range(flist):
print(inverval)
您可以使用numpy数组及其附带的。当您有数百万行时,Numpy比循环更高效
旁白: 因为它们是数据数组,而不是指向数据的指针数组(Python列表就是这样),因为它们将大量计算转移到用C编写的后端,因为他们利用SIMD范式在M多个Data上同时运行S单个I指令
现在回到手头的问题:
diff
函数提供数组中连续元素之间的差异。非常方便,因为我们需要找到这种差异大于已知阈值的地方
import numpy as np
threshold = 1
arr = np.array([1,2,3,4,9,10,11,20])
deltas = np.diff(arr)
# There's a gap wherever the delta is greater than our threshold
gaps = deltas > threshold
gap_indices = np.argwhere(gaps)
gap_starts = arr[gap_indices]
gap_ends = arr[gap_indices + 1]
# Finally, stack the two arrays horizontally
all_gaps = np.hstack((gap_starts, gap_ends))
print(all_gaps)
# Output:
# [[ 4 9]
# [11 20]]
您可以像二维矩阵一样访问所有间隙
:所有间隙[0,1]
将为您提供9
。如果您确实需要答案作为列表列表,只需将其转换为:
all_gaps_list = all_gaps.tolist()
print(all_gaps_list)
# Output: [[4, 9], [11, 20]]
将中迭代方法的运行时与numpy方法进行比较:
import random
import timeit
import numpy
def gaps1(arr, threshold):
deltas = np.diff(arr)
gaps = deltas > threshold
gap_indices = np.argwhere(gaps)
gap_starts = arr[gap_indices]
gap_ends = arr[gap_indices + 1]
all_gaps = np.hstack((gap_starts, gap_ends))
return all_gaps
def gaps2(lst, thr):
seqrange = []
for i in range(len(lst)-1):
if lst[i+1] - lst[i] > thr:
seqrange.append([lst[i], lst[i+1]])
return seqrange
test_list = [i for i in range(100000)]
for i in range(100):
test_list.remove(random.randint(0, len(test_list) - 1))
test_arr = np.array(test_list)
# Make sure both give the same answer:
assert np.all(gaps1(test_arr, 1) == gaps2(test_list, 1))
t1 = timeit.timeit('gaps1(test_arr, 1)', setup='from __main__ import gaps1, test_arr', number=100)
t2 = timeit.timeit('gaps2(test_list, 1)', setup='from __main__ import gaps2, test_list', number=100)
print(f"t1 = {t1}s; t2 = {t2}s; Numpy gives ~{t2 // t1}x speedup")
在我的笔记本电脑上,它提供:
t1=0.0208348000146647s;t2=1.2446780000027502s;Numpy提供约59.0倍的加速比
我的话太快了 我认为这会更有效,更干净一点
def func(lst):
ans=0
final=[]
sol=[]
for i in range(1,lst[-1]+1):
if(i not in lst):
ans+=1
final.append(i)
elif(i in lst and ans>0):
final=[final[0]-1,i]
sol.append(final)
ans=0
final=[]
else:
final=[]
return(sol)
斯坦尼斯拉夫非常感谢你。虽然不知道使用数百万个数字的可行性,但会在测试后更新。