Not a machine
Not a machine

Reputation: 551

Pythonic alternative to nested dictionaries and lists

I am currently using a dictionary keyed on seconds since epoch combined with a nested dictionary and list to store and look up events. The strength is that I can quickly look up a value with good performance (think hash). The weakness is that it is clumsy to search and manipulate the subsequent contents. I can't help but think my approach is not very Pythonic so I am looking for suggestions.

Here is a simple example using integers rather than seconds since epoch:

D = {}

D[1] = {"995" : ["20905", "200101"]}
D[2] = {"991" : ["20901"], "995" : ["20905"]}

eventCode = '995'
error = '90900'

# find entry
if 1 in D:
    # if eventCode exists then append error code
    if D[1][eventCode]:
        D[1][eventCode].append(error)

I can look up D[1] quickly, however the remainder of the code doesn't seem very pythonic. Any suggestions or am I paranoid?

I should check to see if "error" is already in the list. However, I am unsure how to check for membership in this construct. This snippet does not work for me:

if error not in D[1][eventCode]

Upvotes: 5

Views: 1164

Answers (2)

Juan Leni
Juan Leni

Reputation: 7598

Apart from the other suggestions, you could use defaultdict and sets in this way:

from collections import defaultdict

D = defaultdict(lambda: defaultdict( lambda: None))

D[1] = {"995" : {"20905", "200101"}}
D[2] = {"991" : {"20901"}, "995" : {"20905"}}

eventCode = '995'
error = '90900'

tmp = D[1][eventCode]
if tmp is None:
   D[1][eventCode]={error}
else:
   tmp.add(error)

Upvotes: 1

Mikhail Gerasimov
Mikhail Gerasimov

Reputation: 39546

I'm not sure if that's you want, but you can change lists with sets to handle duplicates and use dict.get to skip checking if key exists:

D = {"995" : {"20905", "200101"}}  # dict: str -> set

# 1) event code not exists, nothing changes:
D.get('111', set()).add('7777')
print(D)  # {'995': {'20905', '200101'}}

# 2) event code exists, error already present, nothing changes:
D.get('995', set()).add('20905')
print(D)  # {'995': {'20905', '200101'}}

# 3) event code exists, error not present, error will be added:
D.get('995', set()).add('7777')
print(D)  # {'995': {'20905', '7777', '200101'}}

Upvotes: 2

Related Questions