当您需要将列表中的项目与其后继或前任进行比较时,zip 功能是您的朋友:
x=[10,11,13,70,71,73,170,171,172,174]
threshold = 50
breaks = [i for i,(a,b) in enumerate(zip(x,x[1:]),1) if b-a>threshold]
groups = [x[s:e] for s,e in zip([0]+breaks,breaks+[None])]
print(groups)
[[10, 11, 13], [70, 71, 73], [170, 171, 172, 174]]
-
breaks 将包含元素 (b) 的索引 (i),这些元素 (b) 比其前任 (a) 大超过 treshold 值。
- 再次使用 zip() 可以将这些中断索引配对以形成开始/结束范围,您可以将其应用于原始列表以获取分组。
请注意,我使用固定阈值来检测“巨大”偏差,但您可以使用百分比或您选择的任何公式/条件来代替 if b-a>threshold。如果偏差计算很复杂,您可能需要创建一个 deviates() 函数并在列表推导中使用它:if deviates(a,b) 以便它保持可理解
如果 zip() 和列表推导太高级,您可以使用简单的 for 循环来做同样的事情:
def deviates(a,b): # example of a (huge) deviation detection function
return b-a > 50
groups = [] # resulting list of groups
previous = None # track previous number for comparison
for number in x:
if not groups or deviates(previous, number):
groups.append([number]) # 1st item or deviation, add new group
else:
groups[-1].append(number) # approximately adjacent, add to last group
previous = number # remember previous value for next loop