I wanted to know if the functionality i am trying to implement in python is possible.
I have a global hash called Creatures. Creatures contain sub-hashes called mammals, amphibians, birds, insects.
Mammals have sub-hashes called whales, elephants. Amphibians have sub-hashes called frogs, larvae. Birds have sub-hashes called Eagle, parakeet. Insects have sub-hashes called dragonfly, mosquito.
Again, Eagles have sub-hashes called male, female.
I am counting the frequencies of all these creatures from a text file. For example, if the file is in below format:
Birds Eagle Female
Mammals whales Male
Birds Eagle Female
I should output Creatures[Birds[Eagle[Female]]] = 2
Creatures[mammals[Whales[Male]]] = 1
Is it possible in Python? How can it be done? I am very new to Python and please help is much appreciated. I am comfortable with dictionaries only upto 1 level, i.e. key-> value. But here, there are multiple keys and multiple values. i am not sure how to proceed with this. I am using python 2.6. Thanks in advace!
General Idea: In Python, if we want a dictionary to have multiple values for a single key, we need to store these values in their own container within the dictionary. To do so, we need to use a container as a value and add our multiple values to that container. Common containers are lists, tuples, and sets.
In Python, a Nested dictionary can be created by placing the comma-separated dictionaries enclosed within braces.
First, a given key can appear in a dictionary only once. Duplicate keys are not allowed.
The value assigned to a key in a dictionary can itself be another dictionary
creatures = dict()
creatures['birds'] = dict()
creatures['birds']['eagle'] = dict()
creatures['birds']['eagle']['female'] = 0
creatures['birds']['eagle']['female'] += 1
You need to explicitly create each dictionary, though. Unlike Perl, Python does not automatically create a dictionary when you attempt to treat the value of an unassigned key as such.
Unless, of course, you use a defaultdict
:
from collections import defaultdict
creatures = defaultdict( lambda: defaultdict(lambda: defaultdict( int )))
creatures['birds']['eagle']['female'] += 1
For arbitrary levels of nesting, you can use this recursive definition
dd = defaultdict( lambda: dd )
creatures = dd
creatures['birds']['eagle']['female'] = 0
In this case, you do need to explicitly initialize the integer value, since otherwise the value of creatures['birds']['eagle']['female']
will be assumed to be another defaultdict
:
>>> creatures = dd
>>> type(creatures['birds']['eagle']['female'])
<class 'collections.defaultdict'>
If you just have to "count" things -- and assuming the data file contains all the required level of "hashes" -- that will do the trick:
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
Producing the result:defaultdict(<type 'int'>, {'Mammals-whales-Male': 1, 'Birds-Eagle-Female': 2})
If you require nested dictionary -- post-processing of that result is still possible...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With