2010-09-15 32 views
11

Như một vấn đề quan tâm chung, tôi tự hỏi nếu có một cách thanh lịch/hiệu quả hơn để làm điều này. Tôi có một hàm so sánh hai bộ bắt đầu/kết thúc của các ngày trả về true nếu chúng giao nhau.giao lộ khoảng thời gian trăn

from datetime import date 
def date_intersection(t1, t2): 
    t1start, t1end = t1[0], t1[1] 
    t2start, t2end = t2[0], t2[1] 

    if t1end < t2start: return False 
    if t1end == t2start: return True 
    if t1start == t2start: return True 
    if t1start < t2start and t2start < t1end: return True 
    if t1start > t2start and t1end < t2end: return True 
    if t1start < t2start and t1end > t2end: return True 
    if t1start < t2end and t1end > t2end: return True 
    if t1start > t2start and t1start < t2end: return True 
    if t1start == t2end: return True 
    if t1end == t2end: return True 
    if t1start > t2end: return False 

vì vậy nếu:

d1 = date(2000, 1, 10) 
d2 = date(2000, 1, 11) 
d3 = date(2000, 1, 12) 
d4 = date(2000, 1, 13) 

thì:

>>> date_intersection((d1,d2),(d3,d4)) 
False 
>>> date_intersection((d1,d2),(d2,d3)) 
True 
>>> date_intersection((d1,d3),(d2,d4)) 
True 

, vv

Tôi tò mò muốn biết nếu có một pythonic hơn/nhã/hiệu quả hơn/ít hơn verbose/thường tốt hơn, cách để làm điều này với có thể mxDateTime hoặc một số thông minh hack với timedelta hoặc set()?

Một hình thức thay thế và hữu ích sẽ cho hàm để trả về một tuple bắt đầu/kết thúc ngã tư nếu ai tìm thấy

Cảm ơn

+0

Bạn nên sử dụng timedeltas để biểu thị thời lượng 't1 ⇔ t2' và tôi đang nghĩ về bit tiếp theo. http://docs.python.org/library/datetime.html#datetime.timedelta – msw

Trả lời

19

Nó không thực sự nhiều hơn Pythonic, nhưng bạn có thể chỉ đơn giản là logic để quyết định trên một giao lộ hơi. Đây vấn đề đặc biệt cây trồng lên rất nhiều:

return (t1start <= t2start <= t1end) or (t2start <= t1start <= t2end) 

Để xem lý do tại sao công trình này suy nghĩ về những cách khác nhau có thể là hai khoảng thời gian có thể giao nhau và thấy rằng điểm khởi đầu của người ta phải luôn luôn nằm trong phạm vi của người kia.

+0

có! rất đẹp. Nó vẫn khiến tôi hơi liếc mắt, nhưng bạn đã sụp đổ phân tích trường hợp đầy đủ của tôi thành một biểu hiện rất rõ ràng. Cảm ơn rất nhiều, điều này giúp làm rõ suy nghĩ của tôi. – jjon

+0

Theo thử nghiệm đơn vị của tôi, nó không hoạt động nếu kết thúc 't1' là khởi đầu của' t2'. –

+0

Khi t2start <= t1end? Tôi nghĩ bạn nên kiểm tra lại bài kiểm tra đơn vị của mình. – Amoss

0
if t1end < t2start or t1start > t2end: return False 
if t1start <= t2end or t2start <= t1start: return True 
return False 

Sẽ không bìa rằng tất cả các bộ giao nhau?

+0

Vâng, mã của bạn đơn giản hóa để trả lại t1end> = t2start và t1start <= t2end – Amoss

+0

ah, phải ... 1 thêm – nmichaels

6

Đây là phiên bản cung cấp cho bạn phạm vi giao lộ. IMHO, nó có thể không phải là điều kiện tối ưu nhất, nhưng nó hiển thị rõ ràng khi t2 trùng lặp với t1. Bạn có thể sửa đổi dựa trên các câu trả lời khác nếu bạn chỉ muốn đúng/sai.

if (t1start <= t2start <= t2end <= t1end): 
    return t2start,t2end 
elif (t1start <= t2start <= t1end): 
    return t2start,t1end 
elif (t1start <= t2end <= t1end): 
    return t1start,t2end 
elif (t2start <= t1start <= t1end <= t2end): 
    return t1start,t1end 
else: 
    return None 
+1

FYI ... chuỗi các nhà khai thác so sánh: http://stackoverflow.com/questions/101268/hidden-features-of-python/101945#101945 – fseto

+0

Cảm ơn nhiều vì liên kết đến các nhà khai thác chuỗi, điều đó rất hữu ích. – jjon

+0

Điều này có thể được làm rõ bằng cách sử dụng min vào ngày kết thúc. ví dụ. nếu start1 <= start2 <= end1: return (start2, min (end1, end2)) – JeremyKun

7

Một thay thế và giải pháp hy vọng dễ hiểu hơn:

def has_overlap(A_start, A_end, B_start, B_end): 
    latest_start = max(A_start, B_start) 
    earliest_end = min(A_end, B_end) 
    return latest_start <= earliest_end: 

Chúng tôi có thể nhận được khoảng thời gian sự chồng chéo một cách dễ dàng, đó là (latest_start, earliest_end). Lưu ý rằng latest_start có thể bằng số tiền sớm nhất.

Cần lưu ý rằng điều này giả định rằng A_start <= A_endB_start <= B_end.

+2

Cái này là dễ đọc nhất. Ngoài ra, bạn có thể dễ dàng trả lại (earliest_end-latest_start) để có được phép đo tổng số lượng trùng lặp. – cxrodgers

2
Final Comparison: start <= other_finish and other_start <= finish 

# All of the conditions below result in overlap I have left out the non overlaps 

start <= other_start | start <= other_finish | other_start <= finish | finish <= other_finish 

     0      1      1      0     
     0      1      1      1 
     1      1      1      0   
     1      1      1      1 

Chỉ bắt đầu < = other_finishother_start < = kết thúc cần đến mức khó tin để trả lại một sự trùng lặp.

+0

Một câu trả lời hay sẽ bao gồm một số giải thích là tại sao điều này sẽ giải quyết bất cứ điều gì. – Qirel

Các vấn đề liên quan