Alle Lösungen, die eine Vielzahl von Bedingungen überprüfen, basierend darauf, wo die Bereiche zueinander stehen, können erheblich vereinfacht werden, indem einfach sichergestellt wird, dass ein Bereich vor oder gleichzeitig wie der andere beginnt. Dies können Sie durch den Austausch der Bereiche vorab erreichen.
Dann können Sie eine Überlappung erkennen, wenn der Start des zweiten Bereichs:
- kleiner oder gleich dem Ende des ersten Bereichs ist (wenn die Bereiche inklusiv sind und sowohl die Start- als auch die Endzeiten enthalten); oder
- kleiner ist (wenn die Bereiche den Start einschließen und das Ende ausschließen).
Zum Beispiel (vorausgesetzt, sowohl am Anfang als auch am Ende inklusiv), gibt es nur vier Möglichkeiten für Bereich 2, von denen eine keine Überlappung darstellt (das >
am Ende des Bereichs bedeutet, dass es nicht darauf ankommt, wo der Bereich endet):
|-----| Bereich 1, die Zeilen unten sind alle Bereich 2.
|--> : Überlappung.
|--> : Überlappung.
|---> Überlappung (keine Überlappung im Fall von ausschließendem Ende).
|---> keine Überlappung.
Der Endpunkt des zweiten Bereichs beeinflusst das Ergebnis überhaupt nicht. Daher können Sie in Pseudocode etwas Ähnliches tun (vorausgesetzt, dass s <= e
für alle Bereiche gilt - wenn nicht, müssen Sie sie auch austauschen):
def überschneidet_sich(r1, r2):
if r1.s > r2.s:
tausche r1, r2
return r2.s <= r1.e
Oder die Option mit einer Rekursionsebene:
def überschneidet_sich(r1, r2):
if r1.s <= r2.s:
return r2.s <= r1.e
return überschneidet_sich(r2, r1)
Wenn die Bereiche am Ende ausschließend sind, müssen Sie nur <=
durch <
im Ausdruck, den Sie zurückgeben, ersetzen (in beiden Code-Schnipseln).
Dies beschränkt die Anzahl der Überprüfungen erheblich, die Sie durchführen müssen, da Sie bereits früh die Hälfte des Problems entfernen, indem Sie sicherstellen, dass der erste Bereich niemals nach dem zweiten beginnt.
Und da "Code spricht", hier ist etwas Python-Code, der dies in Aktion zeigt, mit einer ziemlichen Anzahl von Testfällen. Zuerst die InclusiveRange
-Klasse:
class InclusiveRange:
"""Klasse InclusiveRange zur Darstellung einer unteren und oberen Grenze."""
def __init__(self, start, end):
"""Initialisierung, stellt sicher, dass start <= end.
Args:
start: Der Start des Bereichs.
end: Das Ende des Bereichs.
"""
self.start = min(start, end)
self.end = max(start, end)
def __repr__(self):
"""Rückgabe der Darstellung für f-String."""
return f"({self.start}, {self.end})"
def überschneidet_sich(self, other):
"""True, wenn Bereich mit einem anderen überlappt.
Args:
other: Der andere InclusiveRange, gegen den überprüft wird.
"""
# Sehr begrenzte Rekursion, um sicherzustellen, dass der Start des ersten Bereichs
# nicht nach dem Start des zweiten Bereichs liegt.
if self.start > other.start:
return other.überschneidet_sich(self)
# Sehr vereinfachte Überprüfung der Überlappung.
return other.start <= self.end
Dann ein Testfall-Handler, damit wir das Ergebnis eines einzigen Testfalls schön präsentieren können:
def test_fall(range1, range2):
"""Prüfung eines einzelnen Testfalls."""
# Niedrigsten und höchsten Wert für "grafische" Ausgabe erhalten.
low = min(range1.start, range2.start)
high = max(range1.end, range2.end)
# Ausgabe der Bereiche und der Grafik.
print(f"r1={range1} r2={range2}: ", end="")
for val in range(low, high + 1):
is_in_first = range1.start <= val <= range1.end
is_in_second = range2.start <= val <= range2.end
if is_in_first and is_in_second:
print("|", end="")
elif is_in_first:
print("'", end="")
elif is_in_second:
print(",", end="")
else:
print(" ", end="")
# Schließlich Ausgabe des Ergebnisses der Überlappungsprüfung.
print(f" - {range1.überschneidet_sich(range2)}\n")
Und schließlich eine anständige Anzahl von Testfällen, zu denen Sie bei Bedarf weitere hinzufügen können:
# Verschiedene Testfälle, fügen Sie weitere hinzu, wenn Sie die Richtigkeit anzweifeln.
test_fall(InclusiveRange(0, 1), InclusiveRange(8, 9))
test_fall(InclusiveRange(0, 4), InclusiveRange(5, 9))
test_fall(InclusiveRange(0, 4), InclusiveRange(4, 9))
test_fall(InclusiveRange(0, 7), InclusiveRange(2, 9))
test_fall(InclusiveRange(0, 4), InclusiveRange(0, 9))
test_fall(InclusiveRange(0, 9), InclusiveRange(0, 9))
test_fall(InclusiveRange(0, 9), InclusiveRange(4, 5))
test_fall(InclusiveRange(8, 9), InclusiveRange(0, 1))
test_fall(InclusiveRange(5, 9), InclusiveRange(0, 4))
test_fall(InclusiveRange(4, 9), InclusiveRange(0, 4))
test_fall(InclusiveRange(2, 9), InclusiveRange(0, 7))
test_fall(InclusiveRange(0, 9), InclusiveRange(0, 4))
test_fall(InclusiveRange(0, 9), InclusiveRange(0, 9))
test_fall(InclusiveRange(4, 5), InclusiveRange(0, 9))
Beim Ausführen wird die Ausgabe produziert:
r1=(0, 1) r2=(8, 9): '' ,, - False
r1=(0, 4) r2=(5, 9): ''''',,,,, - False
r1=(0, 4) r2=(4, 9): ''''|,,,,, - True
r1=(0, 7) r2=(2, 9): ''||||||,, - True
r1=(0, 4) r2=(0, 9): |||||,,,,, - True
r1=(0, 9) r2=(0, 9): |||||||||| - True
r1=(0, 9) r2=(4, 5): ''''||'''' - True
r1=(8, 9) r2=(0, 1): ,, '' - False
r1=(5, 9) r2=(0, 4): ,,,,,''''' - False
r1=(4, 9) r2=(0, 4): ,,,,|''''' - True
r1=(2, 9) r2=(0, 7): ,,||||||'' - True
r1=(0, 9) r2=(0, 4): |||||''''' - True
r1=(0, 9) r2=(0, 9): |||||||||| - True
r1=(4, 5) r2=(0, 9): ,,,,||,,,, - True
wo jede Zeile hat:
- die beiden bewerteten Bereiche;
- eine grafische Darstellung des "Bereichsraums" (vom niedrigsten Start bis zum höchsten Ende), bei der jedes Zeichen einen Wert in diesem "Bereichsraum" darstellt:
'
zeigt einen Wert nur im ersten Bereich an;
,
zeigt einen Wert nur im zweiten Bereich an;
|
zeigt einen Wert in beiden Bereichen an; und
- zeigt einen Wert in keinem der Bereiche an.
- das Ergebnis der Überlappungsprüfung.
Es ist deutlich zu erkennen, dass Sie nur bei der Überlappungsprüfung true erhalten, wenn es mindestens einen Wert in beiden Bereichen gibt (d. h. ein |
Zeichen). In allen anderen Fällen wird false zurückgegeben.
Fühlen Sie sich frei, weitere Werte hinzuzufügen, wenn Sie weitere Testfälle hinzufügen möchten.
3 Stimmen
Äußerst ähnlich wie stackoverflow.com/questions/306316/…
1 Stimmen
@CharlesBretana Vielen Dank dafür, du hast Recht - das ist fast wie eine zweidimensionale Version meiner Frage!
2 Stimmen
Sehr ähnlich wie stackoverflow.com/questions/117962/…
2 Stimmen
Teile die Situation "Die beiden Datumsbereiche überschneiden sich" in Fälle (es gibt zwei) und teste dann jeweils für jeden Fall.
0 Stimmen
Ich weiß, dass dies als sprachunabhängig markiert wurde, aber für alle, die in Java implementieren: Erfinden Sie das Rad nicht neu und verwenden Sie Joda Time. joda-time.sourceforge.net/api-release/org/joda/time/base/…
0 Stimmen
Wenn Daten NULL-Werte (oder leer) sein können, wenn sie nicht festgelegt sind, gibt es diese Frage, die eine Erweiterung dieser ist.
0 Stimmen
Algorithmus zum Zusammenführen überlappender Intervalle kann einige Hinweise geben.
1 Stimmen
Hallo.. A: StartDate1, B: EndDate1, C: StartDate2, D: EndDate2. Wenn B < C oder A > D, dann nehmen wir an, dass sie sich nicht überschneiden.. Also können wir einfach mit "isintersects = not (B < C oder A > D)" testen, ob es sich überschneidet oder nicht.
0 Stimmen
Noch ein Intervallhilfsprogramm für .Net github.com/AlexeyBoiko/IntervalUtility (Ich bin der Autor)