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'}})})
Answer from Zero Piraeus on Stack Overflow
๐ŸŒ
Python Pool
pythonpool.com โ€บ home โ€บ tutorials โ€บ python lookup tables: dictionaries, defaults, and fast mapping
Learning About the Python Lookup Table
June 26, 2021 - The Python access pattern can stay the same after the data is loaded into a dictionary. In practice, choose bracket lookup when missing keys are errors, get() when a fallback is valid, dispatch tables when names map to functions, and nested dictionaries when multiple keys select one result.
Discussions

json - Building a large (18m keys) lookup table in Python - Stack Overflow
Note that this is not about simply ... sets) of multiple values for many of the keys' values. We could exclude from the lookup table items where there is only a single value for the key, but we also need to be able to update the lookup table from fresh data, and k/v pairs which currently only have a single value might need to be updated ยท So I'm asking what alternative approaches (in Python) that I can ... More on stackoverflow.com
๐ŸŒ stackoverflow.com
python - "Multi-key" dictionary - Code Review Stack Exchange
For a small case it's not a big ... expending memory to store all the keys. For the specific application the python bisect module is handy. It's great for fast searching through sorted data, so its fast for this kind of lookup table:... More on codereview.stackexchange.com
๐ŸŒ codereview.stackexchange.com
July 30, 2017
Python lookup table that returns multiple values - Stack Overflow
I wish to have a lookup table return multiple values. For example, if user's name is "joe", I would like to return an object such as: {'name': 'Joseph', 'gender': 'm', 'xro': 'xy'} At the moment, I More on stackoverflow.com
๐ŸŒ stackoverflow.com
python - Use dictionary as lookup table - Stack Overflow
I have a jinja template that I want to pass a value into (an identifier for a country). The format of the data is a two letter country code (for example "PL" for Poland). Through the template, I n... More on stackoverflow.com
๐ŸŒ stackoverflow.com
People also ask

What is a lookup table in Python?
It is usually a dictionary that maps a key to a value so code can retrieve a result directly instead of using a long chain of conditions.
๐ŸŒ
pythonpool.com
pythonpool.com โ€บ home โ€บ tutorials โ€บ python lookup tables: dictionaries, defaults, and fast mapping
Learning About the Python Lookup Table
How do I avoid a KeyError in a lookup table?
Use get() when a default is valid, check membership when absence matters, or handle KeyError at the boundary where the missing key is meaningful.
๐ŸŒ
pythonpool.com
pythonpool.com โ€บ home โ€บ tutorials โ€บ python lookup tables: dictionaries, defaults, and fast mapping
Learning About the Python Lookup Table
Can lookup-table keys be lists?
No. Dictionary keys must be hashable; use an immutable tuple or another stable representation when a compound key is needed.
๐ŸŒ
pythonpool.com
pythonpool.com โ€บ home โ€บ tutorials โ€บ python lookup tables: dictionaries, defaults, and fast mapping
Learning About the Python Lookup Table
๐ŸŒ
Stack Exchange
gis.stackexchange.com โ€บ questions โ€บ 133123 โ€บ how-do-i-transform-values-using-a-dictionary-or-lookup-table
python - How do I transform values using a dictionary or lookup table? - Geographic Information Systems Stack Exchange
February 4, 2015 - For example, one column may have as source value of "A" that gets transformed to "Z1" and in the same column, "B" gets transformed to "Z2", and still in the same column, "C" gets transformed to "Z1" (multiple source values mapped to same destination value). There are many columns that will need lookups created. I'd prefer to have a different dictionary / lookup table for each column as there will likely be subtle differences between columns and trying to reuse dictionaries will get frustrating. ... Sample using suggestions by @mr.adam: Throws an error on the line if row[key].lower() in lookup(key[1]): with the message TypeError: int object is not subscriptable
๐ŸŒ
Stack Overflow
stackoverflow.com โ€บ questions โ€บ 69595453 โ€บ building-a-large-18m-keys-lookup-table-in-python
json - Building a large (18m keys) lookup table in Python - Stack Overflow
Note that this is not about simply ... sets) of multiple values for many of the keys' values. We could exclude from the lookup table items where there is only a single value for the key, but we also need to be able to update the lookup table from fresh data, and k/v pairs which currently only have a single value might need to be updated ยท So I'm asking what alternative approaches (in Python) that I can ...
Top answer
1 of 6
9

1. Comments on your code

  1. No docstrings! What does your code do and how am I supposed to use it?

  2. No test cases. This ought to be a good opportunity to use doctests.

  3. Given that your purpose here is to implement RPG lookup tables, your design seems a bit hard to use. The printed RPG table probably says something like this:

    1-8     giant spider
    9-12    skeleton
    13-18   brass dragon
    ...
    

    but you have to input it like this (adding one to the limit of each range):

    range_dict((range(1, 9), "giant spider"),
               (range(9, 13), "skeleton"),
               (range(13, 18), "brass dragon"),
               ...)
    

    which would be easy to get wrong.

  4. The design also seems fragile, because it doesn't ensure that the ranges are contiguous. If you made a data entry mistake:

    d = range_dict((range(1, 8), "giant spider"),
                   (range(9, 13), "skeleton"),
                   (range(13, 18), "brass dragon"),
                   ...)
    

    then the missing key would later result in an error:

    >>> d[8]
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    KeyError: 8
    

2. An alternative approach

Here's how I'd implement this lookup table:

from bisect import bisect_left
from collections.abc import Mapping

class LookupTable(Mapping):
    """A lookup table with contiguous ranges of small positive integers as
    keys. Initialize a table by passing pairs (max, value) as
    arguments. The first range starts at 1, and second and subsequent
    ranges start at the end of the previous range.

    >>> t = LookupTable((10, '1-10'), (35, '11-35'), (100, '36-100'))
    >>> t[10], t[11], t[100]
    ('1-10', '11-35', '36-100')
    >>> t[0]
    Traceback (most recent call last):
      ...
    KeyError: 0
    >>> next(iter(t.items()))
    (1, '1-10')

    """
    def __init__(self, *table):
        self.table = sorted(table)
        self.max = self.table[-1][0]

    def __getitem__(self, key):
        key = int(key)
        if not 1 <= key <= self.max:
            raise KeyError(key)
        return self.table[bisect_left(self.table, (key,))][1]

    def __iter__(self):
        return iter(range(1, self.max + 1))

    def __len__(self):
        return self.max

Notes on this implementation:

  1. The constructor takes the maximum for each range (not the maximum plus one), making data entry less error-prone.

  2. The minimum of each range is taken from the end of the previous range, thus ensuring that there are no gaps between ranges.

  3. The collections.abc.Mapping abstract base class provides much of the functionality of a read-only dictionary. The idea is that you supply the __getitem__, __iter__ and __len__ methods, and the Mapping class supplies implementations of __contains__, keys, items, values, get, __eq__, and __ne__ methods for you. (Which you can override if you need to, but that's not necessary here.)

  4. I've used bisect.bisect_left to efficiently look up keys in the sorted table.

2 of 6
6

So, I came across this issue earlier today. Wasn't real thrilled with most of the solutions here, mostly because I wanted to be able to set normal keys, but also set a range of keys all at once when needed, so I came up with this:

class RangedDict(dict):
    """
    A dictionary that supports setting items en masse by ranges, but also supports normal keys.

    The core difference between this and any other dict is that by passing a tuple of 2 to 3 numeric values, an
    inclusive range of keys will be set to that value. An example usage is:

    >>> d = RangedDict({
    ...   (1, 5): "foo"
    ... })
    >>> print d[1]  # prints "foo"
    >>> print d[4]  # also prints "foo"
    >>> print d[5]  # still prints "foo" because ranges are inclusive by default
    >>> d['bar'] = 'baz'
    >>> print d['bar']  # prints 'baz' because this also works like a normal dict

    Do note, ranges are inclusive by default, so 5 is also set. You can control
    inclusivity via the `exclusive` kwarg.

    The third, optional, parameter that can be given to a range tuple is a step parameter (analogous to the step
    parameter in xrange), like so: `(1, 5, 2)`, which would set keys 1, 3, and 5 only. For example:

    >>> d[(11, 15, 2)] = "bar"
    >>> print d[13]  # prints "bar"
    >>> print d[14]  # raises KeyError because of step parameter

    NOTE: ALL tuples are strictly interpreted as attempts to set a range tuple. This means that any tuple that does NOT
    conform to the range tuple definition above (e.g., `("foo",)`) will raise a ValueError.
    """
    def __init__(self, data=None, exclusive=False):
        # we add data as a param so you can just wrap a dict literal in the class constructor and it works, instead of
        # having to use kwargs
        self._stop_offset = 0 if exclusive else 1
        if data is None:
            data = {}

        for k, v in data.items():
            if isinstance(k, tuple):
                self._store_tuple(k, v)
            else:
                self[k] = v

    def __setitem__(self, key, value):
        if isinstance(key, tuple):
            self._store_tuple(key, value)
        else:
            # let's go ahead and prevent that infinite recursion, mmmmmkay
            dict.__setitem__(self, key, value)

    def _store_tuple(self, _tuple, value):
        if len(_tuple) > 3 or len(_tuple) < 2:
            # eventually, it would be nice to allow people to store tuples as keys too. Make a new class like: RangeKey
            # to do this
            raise ValueError("Key: {} is invalid! Ranges are described like: (start, stop[, step])")

        step = _tuple[2] if len(_tuple) == 3 else 1
        start = _tuple[0]
        stop = _tuple[1]

        # +1 for inclusivity
        for idx in xrange(start, stop + self._stop_offset, step):
            dict.__setitem__(self, idx, value)

It uses tuples to describe ranges, which looks rather elegant, if I do say so myself. So, some sample usage is:

d = RangedDict()
d[(1, 15)] = None
d[(15, 25)] = "1d6x1000 cp"

Now you can easily use d[4] and get what you want.

The astute reader will however notice that this implementation does not allow you to use tuples as keys at all in your dict. I don't see that as a common use case, or something elegant to do, in general, so I felt it was worth the tradeoff. However, a new class could be made named along the lines of RangeKey(1, 5, step=2) that could be used to key ranges, thus letting you key tuples as well.

I hope a future reader enjoys my code!

๐ŸŒ
Esri Community
community.esri.com โ€บ t5 โ€บ python-questions โ€บ python-lookup-table โ€บ td-p โ€บ 22577
Solved: Python Lookup Table? - Esri Community
December 5, 2013 - I thought about perhaps using a python dictionary where the name of the dataset in the Database would be the key and the possible search terms could be the values, but when I played with it I couldn't find a way to associate multiple values with a single key in a super simple way.
Find elsewhere
๐ŸŒ
Readthedocs
ttp.readthedocs.io โ€บ en โ€บ latest โ€บ Lookup Tables โ€บ Lookup Tables.html
Lookup Tables โ€” ttp 0.10.0 documentation
lookup_table_name(mandatory) - string to use as a name for lookup table, that is required attribute without it lookup data will not be loaded. ... loader_name (optional) - name of the loader to use to render supplied variables data, default is python. ... If load is csv, first column by default will be used to create lookup dictionary, it is possible to supply key with column name that should be used as a keys for row data.
๐ŸŒ
DaniWeb
daniweb.com โ€บ programming โ€บ software-development โ€บ threads โ€บ 438596 โ€บ fast-dictionary-lookup-with-multiple-keys
python - Fast dictionary lookup with multiple keys. | DaniWeb
October 30, 2012 - dictionary={a:1, b:2, c:3 ...etc} lookup=[a, a, b, c, c ... etc] results = [dictionary[key] for key in lookup if key in dictionary] ... We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology ...
Top answer
1 of 3
3

You have two straightforward choices. One is the standard look-up list, as in Evan's comment:

{'guiseppe': 'Joseph', 'joe': 'Joseph', 'joey': 'Joseph', 'joseph': 'Joseph',
 'Samuel': 'Samuel', 'sam': 'Samuel', 'samuel': 'Samuel', 'shmuel': 'Samuel'}

Now, adapt this to return the full object, rather than the name. Since you didn't specify an object, I'll assume a Person class:

joseph = Person(name = "Joseph", gender = "m", xro = "xy")
samuel = Person(name = "Samuel", gender = "m", xro = "xy")

Now, just insert the objects into your look-up table:

{'guiseppe': joseph, 'joe': joseph, 'joey': joseph, 'joseph': 'Joseph',
 'Samuel': samuel, 'sam': samuel, 'samuel': samuel, 'shmuel': 'Samuel'}

The other look-up method is to remove the extra loop from your existing code; use the in operator:

for canon in name_forms:
    for variant in name_forms[canon]:
        if txt.lower() in variant:
            return canon

You will still need a string-to-object table, but now it's shorter:

{"Joseph": jospeh, "Samuel": samuel}
2 of 3
2

Depends on the problem. What exactly do you want?

I can only come up with something like this:

    def lookup(txt):
        name_forms = {
       'Joseph': ['joe', 'joseph', 'guiseppe', 'joey'], 
       'Samuel': ['sam', 'samuel', 'shmuel', 'kamuel'], 
       'Maria': ['mary', 'marie', 'miriam', 'mariana']}
        for i, canon in enumerate(name_forms):
            for variant in name_forms[canon]:
                if txt.lower() == variant.lower():
                    if i <= 1:
                        gender = 'm'
                        xro = 'xy'
                    else:
                        gender = 'f'
                        xro = 'xx'
                    return {'name': canon, 'gender': gender, 'xro': xro}

    lookup('joey')

I didn't change your look-up method, but it's definitely not effective as others already mentioned.

๐ŸŒ
Delft Stack
delftstack.com โ€บ home โ€บ howto โ€บ python โ€บ lookup table python
Lookup Table in Python | Delft Stack
February 25, 2025 - What are the main methods to implement lookup tables in Python? The article discusses four main methods: ... When should I use a dictionary for a lookup table? Dictionaries are ideal when you have non-sequential keys or when you need to map arbitrary keys to values.
๐ŸŒ
Reddit
reddit.com โ€บ r/learnpython โ€บ optimal way to create a lookup table?
r/learnpython on Reddit: Optimal way to create a lookup table?
December 11, 2017 -

Hey everyone,

I need to map a large number of values to a smaller set of numbers and I'm wondering what the optimal way to do this would be.

My first intuition was to create a dictionary where the key was the output number and the values would be a list of the input numbers. It feels like the data should be structured in this manner since there are far fewer output than input numbers but this method would be like searching a real dictionary by definition to try to find a word.

Since that seems less than optimal, my plan is to create a one-to-one mapping even though the value numbers will be repeated many times.

I know my current idea will work but I can't shake the suspicion that there's a module or strategy I can use to make it even better. Any ideas if there's anything I can do?

Edit - More details:

I have an Excel report that contains 50,000+ rows, each with a unique ID number. These rows are then classified into 1 of 2197 classes.

In the future, I will be without the report. When I import the data, I will only have the unique ID number and will need to find a way to classify each row correctly.

๐ŸŒ
Quora
quora.com โ€บ How-can-a-lookup-table-be-created-using-Python-and-pandas
How can a lookup table be created using Python and pandas? - Quora
Answer (1 of 3): 1. Import pandas: import pandas as pd 2. Create a dictionary with the key-value pairs for the lookup table:lookup_dict = {'A': 1, 'B': 2, 'C': 3} 3. Convert the dictionary to a pandas DataFrame:lookup_df = pd.DataFrame(list(lookup_dict.items()), columns=['key', 'value']) 4. Optio...
๐ŸŒ
Stack Overflow
stackoverflow.com โ€บ questions โ€บ 47193419 โ€บ calling-objects-and-keys-from-lookup-table
python - Calling objects and keys from lookup table - Stack Overflow
FYI, the code I posted works very nicely. The problem, that code has been written for a different lookup table (objects first, keys second configuration).
๐ŸŒ
Techhiccups
techhiccups.com โ€บ home โ€บ python โ€บ python lookup table: a solution to variable lookup errors
Python Lookup Table: A Solution to Variable Lookup Errors - techhiccups.com
January 31, 2024 - Since the hash value is unique for each key, the lookup table can quickly locate the desired value without having to iterate through the entire data structure. To use a lookup table in Python, you need to create a dictionary object and populate it with key-value pairs.
๐ŸŒ
Drbeane
drbeane.github.io โ€บ python โ€บ pages โ€บ collections โ€บ lookup_tables.html
Lookup Tables โ€” Python for Data Science
One common application of dictionaries is to create lookup tables. Letโ€™s say that you have several objects, and each one has a unique identifier assigned to it. Assume that your code has to frequently look up characteristics of the objects based on their identifier.
Top answer
1 of 3
21

Since we are not given any further information about what ranges should be associated with which values, I assume you will transfer my answer to your own problem.

Look-up-Tables are called dictionary in python. They are indicated by curly brackets.

Easy example:

myDict = {1: [1, 2, 3, 4, 5],
          2: [2, 3, 4, 5, 6],
          3: [3, 4, 5, 6, 7]}

Here you create a dictionary with three entries: 1, 2, 3. Each of these entries has a range associated with it. In the example it is of logic range(i, i+5).

You inquire your "Look-Up-Table" just like a list:

print(myDict[2])
>>> [2, 3, 4, 5, 6]

(Note how [2] is not index #2, but actually the value 2 you were looking for)

Often you do not want to create a dictionary by hand, but rather want to construct it automatically. You can e.g. combine two lists of the same length to a dictionary, by using dict with zip:

indices = range(15, 76) # your values from 15 to 75
i_ranges = [range(i, i+5) for i in indices] # this constructs your ranges
myDict = dict(zip(indices, i_ranges)) # zip together the lists and make a dict from it
print(myDict[20])
>>> [20, 21, 22, 23, 24]

By the way, you are not restricted to integers and lists. You can also go like:

myFruits = {'apples': 20, 'cherries': 50, 'bananas': 23}
print(myFruits['cherries'])
>>> 50
2 of 3
3

Following is a linear-interpolating lookup implementation:

from bisect import bisect_left

def lookup(x, xs, ys):
    if x <= xs[0]:  return ys[0]
    if x >= xs[-1]: return ys[-1]

    i = bisect_left(xs, x)
    k = (x - xs[i-1])/(xs[i] - xs[i-1])
    y = k*(ys[i]-ys[i-1]) + ys[i-1]

    return y

For testing:

xs = [1, 2, 4, 8, 16, 32, 64, 128, 256]
ys = [0, 1, 2, 3, 4, 5, 6, 7, 8]
i_xs = [i/1000-500 for i in range(1000000)]

start_time = time.time()
ys = [lookup(x, xs, ys) for x in i_xs]
print("%s secs" % (time.time() - start_time))

I get around 1.8secs.

๐ŸŒ
LabEx
labex.io โ€บ tutorials โ€บ python-how-to-create-lookup-tables-efficiently-466054
Python - How to create lookup tables efficiently
def generate_multiplication_table(max_num): return { (x, y): x * y for x in range(1, max_num + 1) for y in range(1, max_num + 1) } ... ## Lazy evaluation with generators def lazy_lookup_table(limit): return (x**2 for x in range(limit)) def safe_lookup_table(data_dict, default=None): return lambda key: data_dict.get(key, default)
Top answer
1 of 2
3

Let's go through it line by line.

ops1 = {
        "1": print("1"), # this value is actually the value returned by print
        "2": print("2"),
        "4": print("4")
} # when the dictionary is created, everything in it is evaluated,
# so it executes those print calls
# that's why you see all three printed

lis = [1, 2, 3]

for x in range(0, len(lis)-1): # this includes 0 and 1
    if (lis[x] in ops1.keys()): # lis[0] is 1 and lis[1] is 2
        ops1.get(x) # look for 0 and then 1 in the dictionary

Now let's fix it.

ops1 = {
        "1": lambda: print("1"), # this value is now a FUNCTION, which you can call later
        "2": lambda: print("2"),
        "4": lambda: print("4")
} # when the dictionary is created, everything in it is evaluated, but the functions are not called

lis = [1, 2, 3]

for x in range(len(lis)): # goes through 0, 1, and 2
    if lis[x] in ops1: # lis[0] is 1, lis[1] is 2, lis[2] is 3
        ops1.get(str(lis[x]), print)() # look for '1', '2', and '3',
                                       # then call their values

You could improve that last loop like this:

for x in lis:
    ops1.get(str(x), print)()

So, first we look up the key '1'. That corresponds to a function. Then we call the function. This prints the string '1\n'. Then we look up the key '2'. That corresponds to a function. Then we call the function. This prints the string '2\n'. Then we look up the key '3'. This is not present in the dictionary, so it returns a default function. Then we call this default function. This prints the string '\n'.

2 of 2
1

Try this(roughly)

Problem is you are assigning the results of calling print i.e. None, to your lookup table. You want to assign the function definition instead, wo calling it. Then call the lookedup function in your loop.

def print1():
    print(1)

Ops = {
"1" : print1,
"2" : another_func,
...

}

for key in ["1","2","3"]:
    opskey