Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pythonic alternative to (nested) dictionaries with the same keys?

I find myself avoiding dictionaries because, often, nearly half their code is duplicate. I typically do this in nested dictionaries, where all sub-dictionaries contain the same keys, but different values.

I manually create a large parent dictionary, where each key contains a nested dictionary, to be used in external modules. The nested dictionaries all use the same keys to define configuration parameters. This usage is explicit and works but it feels foolish to retype or copy/paste the keys for each nested dictionary I create manually. I am not overly concerned about optimizing memory or performance, just wondering if I should be doing this another, more Pythonic way.

As a trivial example and pattern often seen:

people_dict = {
    "Charles Lindberg": {"address": "123 St.", 
                         "famous": True}, 
    "Me": {"address": "456 St.",
           "famous": False}
    }

>>>people_dict["Charles Lindberg"]["address"]
"123 St."

While the dictionary enables explicit code, it is tedious and error prone to define nested dictionaries with duplicate keys. In this example, half the nested dictionary is code duplicate code common to all the nested dictionaries. I have tried using tuples to eliminate duplicate keys but find this leads to fragile code - any change in position (rather than a dictionary key) fails. This also leads to code that is not explicit and hard to follow.

people_dict = {
        "Charles Lindberg": ("123 St.", True), 
        "Me": ("456 St.", False),
        }    

>>>people_dict["Charles Lindberg"][0]
"123 St."

Instead, I write a class to encapsulate the same information: This successfully reduces duplicate code...

class Person(object):
    def __init__(self, address, famous=False):
        self.address = address
        self.famous = famous

people_dict = [
    "Charles Lindberg": Person("123 St.", famous=False), 
    "Me": Person("456 St."), 
    ]

>>>people_dict["Charles Lindberg"].address
"123 St." 

Creating a class seems a little overkill... The standard data types seem too basic...

I imagine there's better way to do this in Python, without having to write your own class?

What is the best way to avoid duplicate code when creating nested dictionaries with common keys?

like image 205
OnStrike Avatar asked Oct 30 '14 22:10

OnStrike


People also ask

Can dictionaries have same keys?

No, each key in a dictionary should be unique. You can't have two keys with the same value. Attempting to use the same key again will just overwrite the previous value stored. If a key needs to store multiple values, then the value associated with the key should be a list or another dictionary.

Can you have two of the same keys in a dictionary Python?

The straight answer is NO. You can not have duplicate keys in a dictionary in Python.

Can dictionary have same keys with different values?

You can't. Keys have to be unique.


3 Answers

If you want a dict where all the values are dicts with the same or similar keys, you can define a function that takes the values and returns one of the inner dicts.

def hash(address, famous): return {"address": address, "famous": famous}

people_dict = {
    "Charles Lindberg": hash("123 St.", true),
    "Me": hash("456 St.", false)
}
like image 196
Carl Smith Avatar answered Nov 02 '22 23:11

Carl Smith


First, You can read link above to take more information about nametuples: https://docs.python.org/2/library/collections.html#collections.namedtuple

NamedTuples can help you to avoid "duplicate code". You can create a namedtuple for address and use it to define.
I , particularly, prefer Object. OO has better solution for this problem. You can create a method do export object to a dict.

For functional paradigm is better use lists, array and dict, because there are a lot of methods/functions to help with this structs (map, reduce, etc) . If you no pretend to use some functional in your app, go to OO (object oriented) soluction.

Regards Andre

like image 30
Andre Fonseca Avatar answered Nov 03 '22 00:11

Andre Fonseca


It sounds like you have a matrix of data, since every "row" has the same keys (columns), so I'd use a NumPy array:

import numpy as np

dtype = [('name', object), ('address', object), ('famous', bool)]
people = np.array([
        ("Charles Lindberg", "123 St.", True),
        ("Me", "456 St.", False),
        ], dtype)

charlie = people[people['name'] == 'Charles Lindberg'][0]
print charlie['address']

Or using Pandas which is more high-level:

import pandas as pd
people = pd.DataFrame(people_dict)
print people['Charles Lindberg']['address']

That loads your original dict-of-dicts people_dict straight into the matrix very easily, and gives you similar lookup features.

like image 20
John Zwinck Avatar answered Nov 03 '22 01:11

John Zwinck