我很长时间没有找到如何在python中拆分重叠时间的逻辑。
这是我的测试用例时间
案例1:
Entry 1: 9am - 5pm
Test Entry: 10am - 12pm
Output: 9am - 10am, 10am - 12pm, 12pm - 5pm
现在我希望如果输入重叠时间,那么系统应该将它分成不同的时间。像
entry1.start_time = 9:00am
entry1.end_time = 5:00pm
现在,如果我输入此条目
entry2.start_time = 10:00am
entry2.end_time = 12:00pm
然后系统应将其拆分为
9am - 10am, 10am - 12pm, 12pm - 5pm
案例2
Entry 1 - 9am - 5pm
Test Entry 8am - 10am
Then output should be 8am - 10am , 10am - 5pm
案例3 这是案例1的启示
Entry 1 - 9am - 10am
Test Entry 8am - 11am
Then output should be 8am - 11am
我陷入逻辑困境。这是我开始的一些代码
class TimeSplitter(object):
def __init__(self, **kwargs):
self.entries = kwargs.pop('entries', [])
self.test_entry = kwargs.pop('testEntry', '')
def test_overlap(self, entry1, test_entry):
if test_entry.start_time > entry1.start_time and test_entry.start_time < entry1.end_time
pass
我无法继续下去
答案 0 :(得分:1)
<强> Prelimininaries 强>
鉴于您的示例案例,您希望区分基本条目的测试条目间隔,即在算法的结果中不应分割测试条目间隔。
我将首先在更一般的设置中描述解决方案,其中基本和测试输入间隔被视为相同。然后将补充此解决方案以满足保留的测试条目。
此补充假设测试输入间隔不重叠。第二个修改确保在运行算法之前,在概念上将重叠的测试条目间隔折叠为单个间隔。
<强>买者强>
此解决方案不提供收缩包装的python实现,而是伪代码。把它变成有效的python应该是直截了当的。
<强>概要强>
原始时间间隔涵盖当天p
的某一部分。 p
是这些间隔的结合。注意这个联合是一组有序的非重叠区间。
基本思想是通过一组满足3个条件的不同时间间隔来覆盖p
:
p
考虑原始区间集的边界时间集。该集合中的元素按规范排序。构建由该集合中的相邻时间点定义的一系列间隔。结果是包含p
的非空间隔的无间隙并置。
由于p
可能是非连续的,因此构造的序列必须与p
相交才能获得最终结果。这个交叉点没有
从计算集中改变任何间隔;但是,它可能会消除一些。
算法(一般)
在列表tl_ta
中收集所有时间间隔边界。 tl_ta
的元素应该是实际时间的对,以及指示元素是区间的开始还是结束的标志。此标记将用于跟踪p
。
按元素对的第一个组件
迭代排序的时间点列表,构建非重叠区间的结果列表。
要实现这一目标,你需要......
tl_cover
(最初为空)。ta_current
,ta_previous
。cnt_active
,指示当前时间点包含的间隔数(最初为0)。在迭代的每个步骤中,执行以下操作:
如果当前和之前的时间点不同并且有一些活动间隔,请在结果列表中按下新的时间间隔:
if (ta_previous[0] != ta_current[0]) && cnt_active > 0 then
tl_cover.push ( [ta_previous[0], ta_current[0]] );
end if
if ta_current[1] then cnt_active++; end if;
if !ta_current[1] then cnt_active--; end if;
ta_previous = ta_current; ta_current = shift tl_ta;
算法(补码1 - 稳定的测试输入间隔)
为了保持测试条目的间隔不变,在迭代期间保持一个标志b_preserve
,表示测试条目间隔当前是否有效。虽然如此,但不会终止新的间隔。
因此tl_ta
的元组成为三元组,第三个元素表示这个时间点是否来自测试条目。处理测试条目开始/结束时间设置/重置b_preserve
。
tl_ta
应按字典顺序排序,比较元组(tl_ta[_][0], !tl_ta[_][1], tl_ta[_][1] ? tl_ta[_][2] : !tl_ta[_][2])
,以便在相同的时间,......
此约定可防止具有共同边界的多个测试和基本输入间隔之间的干扰。
每次迭代的第一步现在还检查测试条目包含:
if (ta_previous[0] != ta_current[0]) && (cnt_active > 0) && !b_preserve then
tl_cover.push ( [ta_previous[0], ta_current[0]] );
end if
新变量与活动间隔计数器一起维护:
if ta_current[2] then
b_preserve = ta_current[1];
end if;
算法(补码2 - 重叠测试输入间隔)
而不是布尔值b_preserve
使用初始化为0的计数器cnt_active_te
来处理重叠。每次迭代的新检查的第一步:
if (ta_previous[0] != ta_current[0]) && (cnt_active > 0) && (cnt_active_te == 0) then
tl_cover.push ( [ta_previous[0], ta_current[0]] );
end if
维护cnt_active_te
而不是b_preserve
:
if ta_current[2] then
cnt_active_te += ta_current[1] ? 1 : -1;
end if;
答案 1 :(得分:0)
通常情况下 - 给出一个完整的代码并不是一个好主意 - 我同意 - 但是这里看起来像是有效的。基本的想法是 1)首先将input_start转到test_start(如果它们都不相等且input_start为min) 2)总是采用test_start和test_end 3)如果test_end小于输入结束(并且end_input和end_test不相等),则将test_end带到input_end。
下面的代码很少用铃铛和口哨。
def time_to_int(time_str, midnight_0=False):
""" Converts a given time to an int. if midnight_0 is passed and is
True, returns 0, instead of 24
"""
time_str = time_str.lower()
if time_str.find('am') > 0:
return int(time_str.strip().strip('am'))
elif time_str.find('pm') > 0:
if midnight_0:
return (12 + int(time_str.strip().strip('pm'))) % 24
else :
return (12 + int(time_str.strip().strip('pm')))
else :
return -1
def int_to_ampm(time):
if(time <= 12):
return str(time) + 'am'
else:
return str(time-12) + 'pm'
# throw in some tests for the above routine
#print time_to_int(' 9am')
#print time_to_int(' 9AM')
#print time_to_int(' 11Pm')
#print time_to_int('12pM\n')
#print int_to_ampm(12)
#print int_to_ampm(11)
#print int_to_ampm(17)
input_entries = ['9am - 5pm', '9am - 10am']
test_entries = ['10am - 12am', '8am - 10am', '8am - 11am']
for ip in input_entries:
for test in test_entries:
ip_1 = [time_to_int(x) for x in ip.split('-')]
test_1 = [time_to_int(x) for x in test.split('-')]
out_intervals = []
start = min(ip_1[0], test_1[0])
end = max(ip_1[1], test_1[1])
if(start == ip_1[0]) and start != test_1[0]:
out_intervals.append([start, test_1[0]])
out_intervals.append(test_1)
if(end == ip_1[1]) and (ip_1[1] != test_1[1]):
out_intervals.append([test_1[1], end])
print ip_1, test_1, "=>", ["-".join(y) for y in [map(int_to_ampm, x) for x in out_intervals]]
答案 2 :(得分:-1)
以下是我要做的事情:
import time
Entry1 = "9am - 5pm"
Test_Entry = "10am - 12am"
#Split the test into hours
hours = Entry1.split(" - ")
Test_hours = Test_Entry.split(" - ")
#Convert the hours into time objects for comparison
hours24 = [ time.strptime(hour, '%I%p') for hour in hours]
Test_hours24 = [ time.strptime(hour, '%I%p') for hour in Test_hours]
#Case 1
if Test_hours24[0] >= hours24[0] and Test_hours24[1] <= hours24[1]:
print time.strftime('%I%p',hours24[0]) + " - " + time.strftime('%I%p',Test_hours24[0]) + ", " + time.strftime('%I%p',Test_hours24[0]) + " - " + time.strftime('%I%p',Test_hours24[1]) + ", " + time.strftime('%I%p',Test_hours24[1]) + " - " + time.strftime('%I%p',hours24[1])
#Case 2
elif Test_hours24[0] <= hours24[0] and Test_hours24[1] <= hours24[1]:
print time.strftime('%I%p',Test_hours24[0]) + " - " + time.strftime('%I%p',Test_hours24[1]) + ", " + time.strftime('%I%p',Test_hours24[1]) + " - " + time.strftime('%I%p',hours24[1])
#Case 3
elif Test_hours24[0] <= hours24[0] and Test_hours24[1] >= hours24[1]:
print time.strftime('%I%p',Test_hours24[0]) + " - " + time.strftime('%I%p',Test_hours24[1])
else:
print "Error"