How can I represent data like a dictionary but with duplicate keys?

Question:

I have some code like:

def example(*, current_age:int):
    my_final_return={}
    const1 = int(40)
    const2 = int(45)
    const3 = int(50)
    ages_list = (current_age, const1, const2, const3)
    new_list = ()
    for i in ages_list:
        new_list += (i,)
    for i in new_list:
        my_final_return[i] = {
            "current_age": i * 2   
        }
    return my_final_return

When I try using this code with a current_age that matches one of the constant values, I only get three keys in the result:

>>> example(current_age=40)
{40: {'current_age': 80}, 45: {'current_age': 90}, 50: {'current_age': 100}}

I read Duplicate values in a Python dictionary, so I understand that it is not possible to have duplicate keys in the dictionary. To work around this, I tried returning a tuple instead. This allowed me to duplicate "keys", but I only got (40, 40, 55, 50) as the result – the current_age information is missing.

This code will be part of a web API implementation (using FastAPI), so I need to return something that can be converted to JSON.

How can I structure the data to return all the information?

Asked By: Nor

||

Answers:

As per the comments, you can’t force a dictionary to always have 4 keys with 4 corresponding values, if the keys are overlapping. So, a structure as such:

{
    10 : "some text",
    10 : "other text",
    20 : "yet other text"

}

is impossible.

If you always have 4 items in your data structure, then there are multiple options to choose from. For example, you can have a list with 4 items that are single-item dictionaries like this:

item1 = {10 : "some text"}
item2 = {10 : "other text"}
item3 = {20 : "yet other text"}
item4 = {30 : "wuuuut"}

final_result = [item1, item2, item3, item4]

There are numerous possibilities, using a Tuple is another example. The key thing here is: there are always 4 items, and you can loop over the list and perform any logic you like.

Finally, if it really has to be a dictionary, then you should use a list as value per key. Something like this:

final_result = {
    10 : [{"text": "some text"}, {"text":"other text"}],
    20 : [{"text": "yet other text"}],
    30 : [{"text":"wuuut"}]
}

This way, you can ‘reuse’ existing keys by just adding to it. But then again, if you really want to force 4 elements, then a list would be much easier to control.

Answered By: JarroVGIT

Use a list (or tuple) of key-value pairs. By "pair" we simply mean either a list or tuple with two elements, the first of which is what would have been a "key" and the second of which would have been the "value".

(When converted to JSON, lists and tuples will both turn into what JSON calls "arrays", with square-bracket syntax. JSON parsers will usually turn these into lists when you read them back into other Python code.)

Thus, our target desired output (using a list of tuples) might be

[(40, {'current_age': 80}), (40, {'current_age': 80}), (45, {'current_age': 90}), (50, {'current_age': 100})]

And we could produce it like:

def example(*, current_age:int):
    my_final_return = []
    const1 = int(40)
    const2 = int(45)
    const3 = int(50)
    ages_list = (current_age, const1, const2, const3)
    new_list = ()
    for i in ages_list:
        new_list += (i,)
    for i in new_list:
        my_final_return.append(
            (i, {"current_age": i * 2})
        )
    return my_final_return

Or, more simply (there is no reason to make the new_list copy of ages_list; there is no reason to convert integer literals to integer; we can put the constant values directly into the ages_list; and we can use a list comprehension to process the data rather than a for loop):

def example(*, current_age:int):
    return [
        (i, {"current_age": i * 2})
        for i in (i, 40, 45, 50)
    ]
Answered By: Karl Knechtel
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.