Question

Je travaille avec une grande matrice (250x250x30 = 1875000 cellules), et je voudrais un moyen de définir un nombre arbitraire de drapeaux pour chaque cellule dans cette matrice, d'une certaine manière qui est facile à utiliser et raisonnablement efficace de l'espace .

Mon plan original était un tableau de liste 250x250x30, où chaque élément était quelque chose comme: ["FLAG1","FLAG8","FLAG12"]. J'ai ensuite changé pour stocker tout entiers au lieu: [1,8,12]. Ces entiers sont mis en correspondance en interne par des fonctions getter / setter aux chaînes de drapeau. Celui-ci utilise seulement 250Mo avec 8 drapeaux par point, ce qui est bien en termes de mémoire.

Ma question est: suis-je manque une autre façon évidente de structurer ce type de données

Merci à tous pour vos suggestions. J'ai fini par rouler quelques suggestions en un seul, malheureusement je ne peux pas choisir une réponse et à vivre avec les autres upvoting:

EDIT: erm le code initial I eu ici (en utilisant des ensembles que l'élément de base d'un réseau 3d numpy) utilisé beaucoup de mémoire. Cette nouvelle version utilise environ 500 Mo lorsqu'il est rempli de randint(0,2**1000).

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
Était-ce utile?

La solution

Je généralement utiliser un numpy array (vraisemblablement de ints court, 2 octets chacun, puisque vous pouvez besoin de plus de 256 valeurs distinctes) -. qui prendrait moins de 4 Mo pour les <2 millions de cellules

Si, pour une raison que je ne pouvais pas payer la dépendance numpy (par exemple sur App Engine, qui ne supporte pas numpy), j'utiliser la bibliothèque standard

Autres conseils

Votre solution est bien si chaque cellule va avoir un drapeau. Toutefois, si vous travaillez avec un ensemble de données rares où seul un petit paragraphe de vos cellules aura des drapeaux ce que vous voulez vraiment est un dictionnaire. Vous voulez mettre en place la dictonary si la clé est un tuple pour l'emplacement de la cellule et la valeur est une liste de drapeaux comme vous avez dans votre solution.

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

Ici, nous avons la cellule 1,1,1 ont les drapeaux 1,2 et 3 et la cellule 250,250,30 ont les drapeaux 4,5 et 6

edit- tuples clé fixe, merci André et syntaxe de dictionnaire.

Vous pouvez définir des constantes avec différentes, puissance de deux valeurs:

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

Et les utiliser avec la logique booléenne pour stocker les drapeaux dans un seul entier, p.e:.

flags = FLAG1 | FLAG8

Pour vérifier si un drapeau est activé, vous pouvez utiliser l'opérateur &:

flag1_enabled = flags & FLAG1

Si le drapeau est activé, cette expression renvoie une valeur non nulle, qui sera évalué comme vrai dans toute opération booléenne. Si le drapeau est désactivé, l'expression retourne 0, qui est évaluée comme False dans les opérations booléennes.

BitSet est ce que vous voulez, car il vous permet de stocker beaucoup de drapeaux à la fois à l'aide seulement un nombre entier de taille fixe (type int)

Prendre la suggestion de Robbie un peu plus loin ...

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

Vous pouvez également créer une classe d'aide.

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

Vous pouvez également mettre en œuvre des méthodes spéciales de Python comme pour le rendre __contains__ plus facile de travailler avec.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top