Ich suche nach einer guten Möglichkeit, eine Liste potenziell überlappender numerischer Bereiche zu reduzieren (aufzuteilen). Das Problem ähnelt dem dieser Frage: Schnellster Weg, um überlappende Datumsbereiche aufzuteilen , und viele andere.
Die Bereiche sind jedoch nicht nur ganze Zahlen, und ich suche nach einem anständigen Algorithmus, der leicht in Javascript oder Python usw. implementiert werden kann.
Beispieldaten:
Beispiellösung:
Entschuldigung, wenn dies ein Duplikat ist, aber ich muss noch eine Lösung finden.
javascript
algorithms
python
Jollywatt
quelle
quelle
Antworten:
Gehen Sie mit einem Stapel von links nach rechts, um festzustellen, auf welcher Farbe Sie sich befinden. Verwenden Sie anstelle einer diskreten Karte die 10 Zahlen in Ihrem Datensatz als Haltepunkte.
Beginnen Sie mit einem leeren Stapel und setzen Sie ihn
start
auf 0, bis das Ende erreicht ist:start
, und legen Sie sie und alle Farben mit niedrigerem Rang auf den Stapel. Markieren Sie in Ihrer reduzierten Liste den Anfang dieser Farbe.start
und suchen Sie das Ende der aktuellen Farbestart
auf das Ende dieser Farbe, entfernen Sie sie vom Stapel und überprüfen Sie die Farbe mit dem nächsthöheren Rangstart
sich die Farbe innerhalb des Bereichs der nächsten Farbe befindet, fügen Sie diese Farbe der reduzierten Liste hinzu, beginnend mitstart
.In Anbetracht Ihrer Beispieldaten ist dies ein mentaler Durchlauf:
quelle
Diese Lösung scheint die einfachste zu sein. (Oder zumindest am einfachsten zu begreifen)
Alles, was benötigt wird, ist eine Funktion, um zwei Bereiche zu subtrahieren. Mit anderen Worten, etwas, das folgendes ergibt:
Welches ist einfach genug. Dann können Sie einfach jeden der Bereiche durchlaufen, beginnend mit dem niedrigsten, und für jeden Bereich nacheinander alle darüber liegenden Bereiche abziehen. Und da hast du es.
Hier ist eine Implementierung des Range-Subtrahierers in Python:
Mit dieser Funktion können Sie den Rest folgendermaßen erledigen: (Ein "span" bedeutet einen Bereich, da "range" ein Python-Schlüsselwort ist.)
Das gibt
[['red', [12.5, 13.8]], ['blue', [0.0, 2.0]], ['green', [2.0, 3.5]], ['green', [10.0, 12.0]], ['yellow', [3.5, 6.7]], ['orange', [6.7, 10.0]]]
, was richtig ist.quelle
Wenn der Umfang der Daten Ihren Beispieldaten wirklich ähnlich ist, können Sie eine Karte wie die folgende erstellen:
Gehen Sie dann einfach durch diese Karte, um die Bereiche zu generieren
Um zu arbeiten, müssen die Werte in einem relativ kleinen Bereich liegen, wie in Ihren Beispieldaten.
Bearbeiten: Um mit echten Floats zu arbeiten, generieren Sie mithilfe der Karte eine übergeordnete Zuordnung und ziehen Sie dann die Originaldaten heran, um die Grenzen zu erstellen.
quelle
Hier ist eine relativ einfache Lösung in Scala. Es sollte nicht zu schwierig sein, auf eine andere Sprache zu portieren.
apply
Nimmt einenSet
von allen bereits angewendeten Bereichen auf, findet die Überlappungen und gibt dann einen neuen Satz abzüglich der Überlappungen und zuzüglich des neuen Bereichs und der neu aufgeteilten Bereiche zurück.foldLeft
wiederholt Anrufeapply
mit jedem Eingangsbereich.quelle
Halten Sie einfach eine Reihe von Bereichen nach Start sortiert. Bereich hinzufügen, der alles abdeckt (-oo .. + oo). So fügen Sie einen Bereich r hinzu:
quelle