2011-01-21 11 views
6

Mam wiele obiektów, które muszę połączyć z liczbą całkowitą. Obiekty te są obiektami ArcGIS Point (dokładnie to, czym one nie są istotne), które przechowują wartości X i Y dla punktu, jako liczby zmiennoprzecinkowe.Python indeksu dyktować przez obiekt lub dwa pływaki

trzeba odnotować, że, na przykład:

Point(X = 2.765, Y = 3.982) -> 2 
Point(X = 33.9, Y = 98.45) -> 7 
Point(X = 1.23, Y = 2.43) -> 9 
Point(X = 8.342, Y = 6.754) -> 5 

Następnie musi być w stanie sprawdzić otrzymanej wartości przez wartości X i Y. Próbowałem używać obiektów Point jako klucza słownika, ale to nie działa tak, jak gdy odtwarzam obiekt punktowy z wartości X i Y, nie jest on już poprawnie sprawdzany (prawdopodobnie dlatego, że zmienił się identyfikator obiektu) .

W jaki sposób powinienem łączyć te wartości punktów z liczbami całkowitymi. Czy istnieje inny sposób, w jaki mogę używać słownika?

Odpowiedz

4

Klucze słownika Python muszą być niezmiennymi typami.

Możesz użyć krotki podobnej do (2.765, 3.982). Dopóki krotka zawiera tylko typy niezmienne, może być używana jako klucz słownikowy.

Oto moja próba w konsoli:

>>> my_dict[(12.3151, 1.2541)] = "test" 
>>> my_dict[(12.3151, 1.2541)] 
'test' 

Ty mógłby wymyślić prostą konwencję strun jak "2.765, 3.982" obrócić punkt w indeksie, ale to byłoby marnotrawstwo przetwarzania. Ponadto należy zachować ostrożność: jeśli z jakiegoś powodu zdecydujesz się to zrobić, musisz użyć repr zamiast str (here's).

+0

Dzięki. Czy spowoduje to problemy z pływakiem, ponieważ nie mogą być przechowywane dokładnie. Po prostu martwię się, że konwersja wartości pływających na łańcuchy i używanie ich do indeksowania spowoduje problemy z pływającymi elementami, które nie są ładnie konwertowane na łańcuchy (i zmiennymi, których nie można nawet zapisać w pamięci). – robintw

+0

@robintw, jeśli potrzebujesz dokładności zmiennoprzecinkowej, sprawdź moduł dziesiętny http://docs.python.org/library/decimal.html – admalledd

+0

@robintw - nie testowałem tego, ale uważam, że @admalledd jest poprawny. Czy możesz wybrać odpowiedź lub podzielić się tym, jak rozwiązałeś problem? –

1
+1

Ten problem jest nieco trudniejszy, ponieważ __hash__ musi zwracać liczbę całkowitą. Będziesz potrzebował albo unikalnych identyfikatorów całkowitych dla każdego Punktu (co oznacza kod i narzut maszyny z utrzymaniem rejestru) lub transformacji całkowitej, która może odnosić się do '(float, float)' i generować unikalne liczby całkowite - i jestem przy strata za zejście z jednym z tych z mojej głowy. –

+2

@dorkitude: możesz po prostu zrobić hash (some_float), aby przekonwertować float na unikalną liczbę całkowitą - użyj wbudowanego Pythona. –

+0

@josh to fajne! ale problem pozostaje - staramy się przekształcić dwie zmienne w jedną unikalną liczbę całkowitą. –

10

Dodaj metodę mieszania do klasy Point:

... 
def __hash__(self): 
    return hash(self.x)^hash(self.y) 
... 

Innymi słowy, hash punktu jest munging od mieszania na współrzędne x i y.

EDIT: lepsza funkcja hash (w oparciu o komentarze tutaj) jest:

... 
def __hash__(self): 
    return hash((self.x, self.y)) 
... 

Ponieważ Python skróty krotki w sposób hash((p,q)) nie równa hash((q,p)), to pozwoli uniknąć kolizji hash za punkty symetryczne względem przekątnej .

Następnie można korzystać z obiektu Point jako klucze do słowników, umieścić je w zestawach, itp

+0

Brzmi nieźle, ale problem polega na tym, że nie napisałem klasy Point - pochodzi ona z interfejsu ArcGIS API. Czy istnieje metoda "wstawiania"/"zastępowania" do wstawiania tego rodzaju kodu skrótu do metody? – robintw

+1

@robintw Jest: Point .__ hash__ = lambda self: return hash (self.x)^hash (self.y) –

+0

@robintw: Można również utworzyć własną klasę podklasowaną z Point: 'class HashPoint (Point): [definicja klasy ...] ", która może być łatwiejsza do utrzymania. – senderle

1

Dodaj metodę __hash__() do klasy punkcie jak Payne powiedział. Lub ręcznie oblicz wartość skrótu dla każdego punktu. W każdym razie użyj czegoś takiego, jak to, co Python powinien zrobić:

... 
def __hash__(self): 
    return hash((self.x, self.y)) 
... 
Powiązane problemy