5

I think I want to make a 2D dictionary with multiple keys per value.

I know how to make a 2D dictionary using defaultdict:

from collections import defaultdict
2d_dict = defaultdict(dict)

2d_dict['canned_food']['spam'] = 'delicious'

And I know that using regular dictionaries you can make with multiple keys like:

dictionary={('food','canned_food'):spam}

But I want to do something like lookup by tuple-of-keys:

2d_dict[('canned_food','food')]['spam'] = 'delicious'

In the first dimension of dictionary I need ~25 keys per value. Is there a way to do this with defaultdict?

Even if there is a way to do it with dicts is this a reasonable way to make a simple multidimensional lookup table?

smci
  • 32,567
  • 20
  • 113
  • 146
Keith
  • 361
  • 1
  • 5
  • 18
  • https://datascience.stackexchange.com/questions/49529/how-to-create-dictionary-with-multiple-keys-from-dataframe-in-python?noredirect=1#comment56604_49529 Can someone Please answer this question: – KHAN irfan Apr 18 '19 at 12:51
  • Related: [DataScience.SE: How to create dictionary with multiple keys from dataframe in python?](https://datascience.stackexchange.com/questions/49529/how-to-create-dictionary-with-multiple-keys-from-dataframe-in-python?noredirect=1#comment56604_49529) – smci Dec 09 '19 at 01:18
  • (@KHANirfan: you have to show the title, otherwise noone would know it was a Related link, and might wrongly assume your comment was spam) – smci Dec 09 '19 at 01:18
  • Strictly this question is asking *"Create and lookup 2D dictionary **whose keys are tuple-of-keys**"*. That goes beyond just passing in a tuple-of-keys to a create function, which is what it sounds like at first glance.... – smci Dec 09 '19 at 01:20
  • ...and moreover you want **order-independent lookup** (as if the keys are a set/frozenset, rather than a tuple): `twod_dict[('canned_food','food')]` is the reverse order to what you created. – smci Dec 09 '19 at 01:24

1 Answers1

11

Apart from 2d_dict being an invalid variable name (it starts with a digit), your existing solution already works:

>>> from collections import defaultdict
>>> d2_dict = defaultdict(dict)
>>> d2_dict[('canned_food', 'food')]['spam'] = 'delicious'
>>> d2_dict
defaultdict(<type 'dict'>, {('canned_food', 'food'): {'spam': 'delicious'}})

In fact, you don't even need the parentheses - Python will still recognise your key as a tuple:

>>> d2_dict['fresh_food', 'food']['eggs'] = 'delicious'
>>> d2_dict
defaultdict(<type 'dict'>, {('canned_food', 'food'): {'spam': 'delicious'},
('fresh_food', 'food'): {'eggs': 'delicious'}})

... and, yes, it's a perfectly reasonable way to build a 2D+1D lookup table.

If you want to build a 3D lookup table using nested dicts instead of tuple keys, this works:

>>> d3_dict = defaultdict(lambda: defaultdict(dict))
>>> d3_dict['dried_food']['food']['jerky'] = 'chewy'
>>> d3_dict
defaultdict(<function <lambda> at 0x7f20af38a2a8>, 
{'dried_food': defaultdict(<type 'dict'>, {'food': {'jerky': 'chewy'}})})
Zero Piraeus
  • 56,143
  • 27
  • 150
  • 160
  • Thank you, I had obviously tried the example ( with out the invalid variable name) I must have had a typo. You are right though it does just work. – Keith Nov 10 '12 at 21:38
  • How do I access the dictionary. I thought: `print d2_dict['fresh_food']['eggs']` would print delicious but it comes up with an error. If I use a dictionary without a list it works fine. Do I have to do somethin special to access the dict? – Keith Nov 11 '12 at 20:40
  • `'fresh_food'` isn't a key in the top level dictionary - `('fresh_food', 'food')` is. So you'd use `print d2_dict['fresh_food', 'food']['eggs']`. – Zero Piraeus Nov 11 '12 at 23:03
  • Maybe I asked the question incorrectly. I want 'fresh_food' and/or 'food' to both be separate keys. I don't want the entire list ['fresh_food','food'] to be a key. – Keith Nov 11 '12 at 23:09
  • 1
    If you want multiple keys for a single value, you need to add them separately, as two different items in the dict. – Zero Piraeus Nov 11 '12 at 23:12
  • Okay thank you for all your help. This is what I was originally trying to avoid as I have a large number of keys, it makes for ugly looking code. I will make due however. When I get a little more familiar with python I will try to construct a work around. – Keith Nov 11 '12 at 23:21
  • I am sorry I am new to the community, The given answer does not answer my questions as I intended and we worked that out using the comments. I had hoped this would allow a user that did have a work around to post another answer. Would it be better etiquette to repost the question? – Keith Nov 11 '12 at 23:58