简体   繁体   English

如何对彼此相距 n 的列表元素进行分组

[英]How to group elements of a list that are within n of each other

I have two lists:我有两个清单:

list_1 = []
list_2 = [1.0, 3.0, 3.15, 1.03, 6.0, 7.0]

And I want to sort through this list and merge elements that are within (in this case) 0.15 of each other.我想对这个列表进行排序并合并(在这种情况下)彼此0.15的元素。

So by the end of this, list_1 with contain the following values:因此,到此结束时, list_1包含以下值:

[[1.0, 1.03],[3.0, 3.15]]

Because 1.0 , 1.03 were within 0.15 of each other and 3.0 , 3.15 were also within 0.15 of each other.因为1.01.03彼此相差在 0.15 以内,而3.03.15也在彼此相差 0.15 以内。

This can also be more than just pairs, so for instance if I had 3.16 , that is within range of 3.15 , so it would be added to the group, ie:这也可以不仅仅是对,例如,如果我有3.16 ,即在3.15的范围内,那么它将被添加到组中,即:

list_2 = [1.0, 3.0, 3.15, 1.03, 6.0, 7.0, 3.16]

outputs:输出:

[[1.0,1.03],[3.0,3.15,3.16]]

How can I do this?我怎样才能做到这一点?

Thanks for the help!谢谢您的帮助!

networkx is overkill here. networkx在这里太过分了。 Just sort the list first, then iterate and yield off a chunk when the difference between previous and current is larger than your delta.只需先对列表进行排序,然后在先前和当前之间的差异大于您的增量时迭代并产生一个块。

>>> list_2 = [1.0, 3.0, 3.15, 1.03, 6.0, 7.0, 3.16]
>>> list_2.sort()
>>> delta = 0.15
>>> list_1 = []
>>> prev = -float('inf')
>>> for x in list_2:
...     if x - prev > delta:
...         list_1.append([x])
...     else:
...         list_1[-1].append(x)
...     prev = x
...
>>> list_1
[[1.0, 1.03], [3.0, 3.15, 3.16], [6.0], [7.0]]
>>> [x for x in list_1 if len(x) > 1]
[[1.0, 1.03], [3.0, 3.15, 3.16]]

To split the list on gaps of a given size, you can use zip to compare elements with their neighbours, giving the position of breaks in the sequence.要根据给定大小的间隙拆分列表,您可以使用 zip 将元素与其相邻元素进行比较,从而在序列中给出 position 的中断。 Then zip again to turn these break positions into ranges of the original data.然后 zip 再次将这些中断位置转换为原始数据的范围。

data = [1, 2, 5, 6, 7, 9, 22, 24, 26, 29] 
gap  = 2

breaks  = [ i for i,(a,b) in enumerate(zip(data,data[1:]),1) if abs(a-b) > gap ]
result  = [ data[s:e] for s,e in zip([0]+breaks,breaks+[len(data)]) ]

print(result)
[[1, 2], [5, 6, 7, 9], [22, 24, 26], [29]]

Note that this will work on unsorted lists as well请注意,这也适用于未排序的列表

The technique can be generalized in a function that will split any list on any given condition:该技术可以在 function 中推广,它将在任何给定条件下拆分任何列表:

def splitList(A,condition):
    breaks = [i for i,(a,b) in enumerate(zip(A,A[1:]),1) if condition(a,b)]
    return [A[s:e] for s,e in zip([0]+breaks,breaks+[len(A)])]


data = [1, 2, 5, 6, 7, 9, 22, 24, 26, 29] 
gap=2

result = splitList(data,lambda a,b: abs(a-b)>gap)
print(result)
[[1, 2], [5, 6, 7, 9], [22, 24, 26], [29]]

data   = [1, 2, 5, 6, 4,2,10,15,14,7,9,12]
ascend = splitList(data,lambda a,b: a>b) # split ascending streaks
print(ascend)
[[1, 2, 5, 6], [4], [2, 10, 15], [14], [7, 9, 12]]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM