Search code examples
pythonlistdictionaryenumerate

Weird response with enumerate and dict in python


Using the dict(enumerate(x)), we get the { (index, value) }. Instead, I need { (value, index) }. So, I've written this code...

idx= { n:i for i, n in enumerate(x)}

It works with some inputs and fails with others. Here's an input where it is failing.

x= [73,74,75,71,69,72,76,73]

, Why is it failing? and what should be done?


Solution

  • Why is it failing?

    We know that for:

    x = [73,74,75,71,69,72,76,73, 99]  # note the additional list item
    

    The result:

    {73: 7, 74: 1, 75: 2, 71: 3, 69: 4, 72: 5, 76: 6, 99: 8}
    

    is "bad" for at least the first key in the dictionary. The reason it is bad (as others have pointed out) is that there are duplicate entries in the list x and as we process them we are conceptually doing:

    idx = {}
    idx[73] = 0
    idx[73] = 7
    print(idx)
    

    What should be done?

    We don't know what you actually expect for the key of 73. I think there is a good chance you want the value 0 but perhaps you want the value [0, 7] showing both indexes of 73 in the original list.

    The other wrinkle is not knowing how the additional item 99 (occurring after the duplicated 73) should be assigned a value. Do we keep the existing index entry 8 or do we want that to be a new 7 effectively replacing the duplicate?

    Determining how to get some other result is fairly straight forward and I'll give you several things you can try.

    Option 1:

    I want the keys to have their actual first list indexes:

    73 --> 0
    99 --> 8
    
    idx_expected = {73: 0, 74: 1, 75: 2, 71: 3, 69: 4, 72: 5, 76: 6, 99: 8}
    idx_actual = {}
    for index, value in enumerate(x):
        if value not in idx_actual:
            idx_actual[value] = index
    print(idx_actual == idx_expected)
    

    Option 2:

    I want the keys to have their first list indexes but if there is a duplicate, I just want to pretend it did not exist:

    73 --> 0
    99 --> 7
    
    ## -------------
    idx_expected = {73: 0, 74: 1, 75: 2, 71: 3, 69: 4, 72: 5, 76: 6, 99: 7}
    idx_actual = {n:i for i, n in enumerate(dict.fromkeys(x))}
    print(idx_actual == idx_expected)
    ## -------------
    

    Option 3:

    I want to capture the fact that there could be duplicates in the original list by setting the values in the resulting dictionary to a list of original indexes.

    73 --> [0, 7]
    99 --> [8]
    
    ## -------------
    idx_expected = {73: [0, 7], 74: [1], 75: [2], 71: [3], 69: [4], 72: [5], 76: [6], 99: [8]}
    idx_actual = {}
    for index, value in enumerate(x):
        idx_actual.setdefault(value, []).append(index)
    print(idx_actual == idx_expected)
    ## -------------