如何在python中分隔一些重叠的时间段?
How to separate some overlapping time periods in python?
我有一个不同时间段的列表,开始和结束,比方说:
[(0, 50), (40, 70), (60,100), (65, 105), (90, 120), (110, 150) ]
我需要以某种方式找到重叠的时间范围并将这些时间段分配到不同的层中,每个层中没有重叠,例如上面的列表结果应该是:
[(0, 50, 'layer 1'), (60,100, 'layer 1'), (110,150, 'layer 1'),
(40,70, 'layer 2'), (90,120, 'layer 2'),
(65,105, 'layer 3')]
现在我在 start_time/end_time 中添加了一个“+”/“-”符号,然后对它们进行排序。我坚持下一步。
一种方法是创建一个包含不同层的列表,并用元组填充它,在需要时动态创建一个新层。
# sort the data if it is not already in the order we need
data = sorted(data, key=lambda x: x[1])
data = sorted(data, key=lambda x: x[0])
# build layers as a list of lists
# the outer list will contain the layer levels
# the inner list will contain the periods/tuples in each layer
layers = [[data[0] + ('layer 1',)]] # initialize layer 1
for period in data[1:]: # get one period at a time and find which layer is a good fit
for lay, temp in enumerate(layers):
if period[0] > temp[-1][1]:
# period starts after current layer's last period's end
# add third element to tuple and append to layer
temp.append(period + (f'layer {lay + 1}',))
break
else:
# did not find a layer that can hold current period, create a new layer
layers.append([period + (f'layer {len(layers) + 1}',)])
# flatten layers
layers = [e for L in layers for e in L]
输出
[(0, 50, 'layer 1'), (60, 100, 'layer 1'), (110, 150, 'layer 1'), (40, 70, 'layer 2'), (90, 120, 'layer 2'), (65, 105, 'layer 3')]
另一个解决方案,使用defaultdict
:
from collections import defaultdict
def find_layer(start, end, layers):
l = 0
while layers[l] > start:
l += 1
layers[l] = end
return l
lst = [(0, 50), (40, 70), (60,100), (65, 105), (90, 120), (110, 150)]
# assuming lst is already sorted
# lst = sorted(lst)
layers = defaultdict(int)
for start, end in lst:
print(start, end, 'layer_{}'.format(find_layer(start, end, layers) + 1))
打印:
0 50 layer_1
40 70 layer_2
60 100 layer_1
65 105 layer_3
90 120 layer_2
110 150 layer_1
我有一个不同时间段的列表,开始和结束,比方说:
[(0, 50), (40, 70), (60,100), (65, 105), (90, 120), (110, 150) ]
我需要以某种方式找到重叠的时间范围并将这些时间段分配到不同的层中,每个层中没有重叠,例如上面的列表结果应该是:
[(0, 50, 'layer 1'), (60,100, 'layer 1'), (110,150, 'layer 1'),
(40,70, 'layer 2'), (90,120, 'layer 2'),
(65,105, 'layer 3')]
现在我在 start_time/end_time 中添加了一个“+”/“-”符号,然后对它们进行排序。我坚持下一步。
一种方法是创建一个包含不同层的列表,并用元组填充它,在需要时动态创建一个新层。
# sort the data if it is not already in the order we need
data = sorted(data, key=lambda x: x[1])
data = sorted(data, key=lambda x: x[0])
# build layers as a list of lists
# the outer list will contain the layer levels
# the inner list will contain the periods/tuples in each layer
layers = [[data[0] + ('layer 1',)]] # initialize layer 1
for period in data[1:]: # get one period at a time and find which layer is a good fit
for lay, temp in enumerate(layers):
if period[0] > temp[-1][1]:
# period starts after current layer's last period's end
# add third element to tuple and append to layer
temp.append(period + (f'layer {lay + 1}',))
break
else:
# did not find a layer that can hold current period, create a new layer
layers.append([period + (f'layer {len(layers) + 1}',)])
# flatten layers
layers = [e for L in layers for e in L]
输出
[(0, 50, 'layer 1'), (60, 100, 'layer 1'), (110, 150, 'layer 1'), (40, 70, 'layer 2'), (90, 120, 'layer 2'), (65, 105, 'layer 3')]
另一个解决方案,使用defaultdict
:
from collections import defaultdict
def find_layer(start, end, layers):
l = 0
while layers[l] > start:
l += 1
layers[l] = end
return l
lst = [(0, 50), (40, 70), (60,100), (65, 105), (90, 120), (110, 150)]
# assuming lst is already sorted
# lst = sorted(lst)
layers = defaultdict(int)
for start, end in lst:
print(start, end, 'layer_{}'.format(find_layer(start, end, layers) + 1))
打印:
0 50 layer_1
40 70 layer_2
60 100 layer_1
65 105 layer_3
90 120 layer_2
110 150 layer_1