Frage

Ich arbeite mit einer großen Matrix (250x250x30 = 1.875.000 Zellen), und ich würde einen Weg, wie eine beliebige Anzahl von Flags für jede Zelle in dieser Matrix zu setzen, in gewisser Weise, dass und einigermaßen Raum einfach zu bedienen ist effizient .

Mein ursprünglicher Plan war ein 250x250x30-Listenfeld, wobei jedes Element so etwas wie war: ["FLAG1","FLAG8","FLAG12"]. Habe ich es dann nur ganze Zahlen, anstatt zu speichern: [1,8,12]. Diese Zahlen werden intern von Getter / Setter-Funktionen auf die ursprünglichen Flagge Strings abgebildet. Dieser verwendet nur 250mb mit 8 Flags pro Punkt, der in Bezug auf Speicher in Ordnung ist.

Meine Frage ist: bin ich eine andere offensichtliche Möglichkeit fehlt, diese Art von Daten zu strukturieren

Danke allen für Ihre Anregungen. Ich landete ein paar Vorschläge in eine rollende, leider kann ich nur eine Antwort auswählen und mit upvoting die anderen zu leben haben:

EDIT: ERM den ursprünglichen Code I hatte hier verwendet, eine Menge Speicher (Sets als Basiselement einer 3D numpy Array). Diese neue Version verwendet um 500mb, wenn sie mit randint(0,2**1000) gefüllt.

import numpy

FLAG1=2**0
FLAG2=2**1
FLAG3=2**2
FLAG4=2**3

(x,y,z) = (250,250,30)

array = numpy.zeros((x,y,z), dtype=object)


def setFlag(location,flag):
    array[location] |= flag
def unsetFlag(location,flag):
    array[location] &= ~flag
War es hilfreich?

Lösung

würde ich in der Regel verwenden, um einen numpy Array (vermutlich von kurzen Ints, jeweils 2 Byte, da können Sie muß mehr als 256 verschiedene Werte.) - das würde weniger als 4 MB für die <2 Millionen Zellen

aus irgendeinem Grunde, wenn ich nicht die numpy Abhängigkeit leisten konnte (zB auf App Engine, die nicht numpy nicht unterstützt), würde ich die Standard-Bibliothek verwenden

Andere Tipps

Ihre Lösung ist in Ordnung, wenn jede einzelne Zelle eine Fahne haben wird. Allerdings, wenn Sie mit einem spärlichen Daten-Set, wo nur ein kleiner Abschnitt Ihrer Zellen Flaggen müssen arbeiten, was Sie wirklich wollen, ist ein Wörterbuch. Sie würden die dictonary einrichten wollen so dass der Schlüssel ein Tupel für den Standort der Zelle ist und der Wert ist eine Liste von Flags, wie Sie in Ihrer Lösung haben.

allFlags = {(1,1,1):[1,2,3], (250,250,30):[4,5,6]}

Hier haben wir die 1,1,1 Zelle die Fahnen haben 1,2 und 3 und die Zelle 250,250,30 haben die Flaggen 4,5 und 6

Edit- Taste Tupel fixiert dank Andre und Wörterbuch-Syntax.

Sie können einige Konstanten mit unterschiedlicher, Leistung von zwei Werten wie definieren:

FLAG1 = 0x01
FLAG8 = 0x02
FLAG12 = 0x04
...

Und sie mit dem Booleschen Logik verwenden, um die Flags zu speichern nur in einer ganzen Zahl, P.E:.

flags = FLAG1 | FLAG8

Um zu überprüfen, ob ein Flag aktiviert ist, können Sie den & Operator verwenden:

flag1_enabled = flags & FLAG1

Wenn das Flag aktiviert ist, dieser Ausdruck wird wieder einen Wert ungleich Null, die als wahr in jeder Volumen-Operation ausgewertet. Wenn das Flag deaktiviert ist, wird der Ausdruck 0 zurück, dass als falsch in Boolesche Operationen ausgewertet wird.

BitSet ist, was Sie wollen, da es Ihnen viele Fahnen auf einmal speichern können mit nur eine feste Größe integer (Int-Typ)

Unter Robbie Vorschlag einen Schritt weiter ...

flags = set()
x, y, flag = 34, 201, 3
flags.add((x, y, flag)) # set flag 3 at position (34, 201)
if (3, 2, 1) in flags: # check if flag 1 is at position (3, 2)
    # do something
else:
    # do something else

Sie können auch eine Hilfsklasse erstellen.

class Flags(object):
    def __init__(self):
        self.data = set()
    def add(self, x, y, flag):
        self.data.add((x, y, flag))
    def remove(self, x, y, flag):
        self.data.remove((x, y, flag))
    def contains(self, x, y, flag):
        return (x, y, flag) in self.data

Sie können auch Python spezielle Methoden wie __contains__ implementieren, um es einfacher zu arbeiten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top