2013-06-17 16 views
6

Chciałem wiedzieć, czy funkcja, którą próbuję zaimplementować w Pythonie, jest możliwa.Wiele poziomów kluczy i wartości w Pythonie

Mam globalny skrót o nazwie Creatures. Stworzenia zawierają subhacki zwane ssakami, płazy, ptaki, owady.

Ssaki mają subhashę zwaną wielorybami, słoniami. Płazy mają subhrazy nazwane żabami, larwami. Ptaki mają subhrazy o nazwie Eagle, parakeet. Owady mają sub-haszty zwane ważką, komarem.

Znów, Orły mają subhashy zwane męskimi, żeńskimi.

Liczę częstotliwości wszystkich tych stworzeń z pliku tekstowego. Na przykład, jeśli plik znajduje się poniżej formatu:

Birds Eagle Female 
Mammals whales Male 
Birds Eagle Female 

I should output Creatures[Birds[Eagle[Female]]] = 2 
       Creatures[mammals[Whales[Male]]] = 1 

Czy to możliwe w Pythonie? Jak można to zrobić? Jestem bardzo nowy w Pythonie i proszę o pomoc jest bardzo ceniona. Czuję się komfortowo ze słownikami tylko do 1 poziomu, tj. Klucz-> wartość. Ale tutaj jest wiele kluczy i wiele wartości. nie jestem pewien, jak to zrobić. Używam Pythona 2.6. Dzięki w advace!

+1

Czy powinien pozwolić na arbitralny poziom zagnieżdżenia? – J0HN

+0

Po prostu musisz "liczyć", czy oczekujesz więcej przetwarzania danych? –

+0

@ J0HN Tak, Sylvain: liczba będzie dobrym początkiem, później mogę spróbować więcej przetwarzania. –

Odpowiedz

2

Jeśli trzeba tylko rzeczy „count” - i przy założeniu, że plik danych zawiera wszystkie wymagane poziomie „skrótów” - to załatwi:

import collections 

result = collections.defaultdict(int) 

with open("beast","rt") as f: 
    for line in f: 
     hashes = line.split() 
     key = '-'.join(hashes) 
     result[key] += 1 

print result 

Produkcja wynik:
defaultdict(<type 'int'>, {'Mammals-whales-Male': 1, 'Birds-Eagle-Female': 2})

Jeśli wymagają zagnieżdżone słownika - post-processing tego wyniku jest jeszcze możliwe ...

17

Wartość przypisana do klawisza w słowniku może sama być inny słownik

creatures = dict() 
creatures['birds'] = dict() 
creatures['birds']['eagle'] = dict() 
creatures['birds']['eagle']['female'] = 0 
creatures['birds']['eagle']['female'] += 1 

Trzeba wyraźnie tworzyć każdy słownika, choć. W przeciwieństwie do Perla, Python nie tworzy automatycznie słownika, gdy próbujesz traktować wartość nieprzypisanego klucza jako takiego.

O ile, oczywiście, użyć defaultdict:

from collections import defaultdict 
creatures = defaultdict(lambda: defaultdict(lambda: defaultdict(int))) 
creatures['birds']['eagle']['female'] += 1 

dla dowolnych poziomów zagnieżdżenia, można użyć tej rekurencyjną definicję

dd = defaultdict(lambda: dd) 
creatures = dd() 
creatures['birds']['eagle']['female'] = 0 

W tym przypadku nie trzeba jawnie zainicjować wartość całkowita, ponieważ w przeciwnym razie przyjęta zostanie wartość creatures['birds']['eagle']['female'], która będzie inna: defaultdict.

+0

ptaki, zwierzęta itp. To tylko przykłady, a nie faktyczne wpisy.Właściwie, muszę odczytać z pliku i dodać je automatycznie –

1

Nie eleganckie, ale działa:

result = {} 
for line in input_file.split("\n"): 
    curdict = result 
    values = line.split(" ") 
    for item in values[:-1]: 
     if item not in curdict: 
      curdict[item] = {} 
     curdict = curdict[item] 
    last_item = values[-1] 
    if last_item not in curdict: 
     curdict[last_item] = 0 
    curdict[last_item] += 1 

To prawdopodobnie można zapisać w czystszy sposób, ale przynajmniej działa i pozwala na arbitralny poziom zagnieżdżenia, chyba że masz inny poziom zagnieżdżenia dla tego samego "obiektu" (np. Birds Eagle Female i Birds Eagle nie zadziała)

Powiązane problemy