Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple levels of keys and values in Python

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!

like image 833
Justin Carrey Avatar asked Jun 17 '13 18:06

Justin Carrey


People also ask

Can you have multiple values for a key in Python?

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.

How do you create a multi level dictionary in Python?

In Python, a Nested dictionary can be created by placing the comma-separated dictionaries enclosed within braces.

Can you have multiple of the same key in a dictionary python?

First, a given key can appear in a dictionary only once. Duplicate keys are not allowed.


2 Answers

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'>
like image 196
chepner Avatar answered Sep 21 '22 11:09

chepner


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...

like image 20
Sylvain Leroux Avatar answered Sep 23 '22 11:09

Sylvain Leroux