1

I have a dictionary dic with this key and value pair: (note: this dic is bijective, i.e: one-to-one mapping)

dic = {
    0: 0, 
    30: 1, 
    35: 2, 
    42: 3, 
    53: 4, 
    54: 5, 
    55: 6, 
    81: 7, 
    83: 8, 
    95: 9, 
    99: 10
}

In my source code, there is list L which is generated from a particular computation. Values in L are actually associated with dic values. So, based on dic, I want this L list:

L = [0, 0, 7, 2, 2, 1, 9]

to be converted to key values from dic. This is the desired output out:

out = [0, 0, 81, 35, 35, 30, 95] 

What kind of list comprehension can I use to achieve the desired output?

2 Answers2

4

You can create the inverted dictionary from the original one and use that to get desired result as:

dic = {0: 0, 
30: 1, 
35: 2, 
42: 3, 
53: 4, 
54: 5, 
55: 6, 
81: 7, 
83: 8, 
95: 9, 
99: 10}

invertedDic = {v:k  for k, v in dic.items()}
L = [0, 0, 7, 2, 2, 1, 9]
res = [invertedDic[elt] for elt in L]
print(res)

Output:

[0, 0, 81, 35, 35, 30, 95]

Also, it is not recommended to use keywords like dict for object names.

Krishna Chaurasia
  • 8,924
  • 6
  • 22
  • 35
  • 1
    This is idiomatic, a word of caution, though. If two keys share the same value, it will (silently) use the last found key as value. With an explicit loop one can make sure to catch this case and throw an error, if the dict is not bijective. – Jan Christoph Terasa Feb 18 '21 at 08:17
  • Your solution worked perfectly. Thank you. If I may ask a question again, does ```elt``` have a specific meaning? – Dionisius Pratama Feb 18 '21 at 08:19
  • 1
    `elt` represent the elements of the list being iterated over. It is preferred to directly use `for elt in lst` instead of `for i in range(len(lst): print(lst[i])`. `elt` in the first case is the representation for `list[i]` in the second scenario. – Krishna Chaurasia Feb 18 '21 at 08:22
  • @JanChristophTerasa, in ```dict```, there are actually 51 pairs of key and value (I don't write them all here because I think it is not necessary), and they are bijective. So, there would be no error with that case. – Dionisius Pratama Feb 18 '21 at 08:22
  • 1
    @DionisiusPratama Sure, it will work in the case given, but I just wanted to note that it can be "dangerous" to use as a general inversion of a dict, and can lead to "surprising" results. It answers the question as stated just fine (and thus I upvoted it). – Jan Christoph Terasa Feb 18 '21 at 08:29
  • 1
    I agree with @JanChristophTerasa that it is good to point out that limitation so that the others with the similar problem don't directly use the code without knowing the limitations. – Krishna Chaurasia Feb 18 '21 at 08:31
  • 2
    See also https://stackoverflow.com/questions/483666/reverse-invert-a-dictionary-mapping for some more ideas of how to handle the non-bijective cases. – Jan Christoph Terasa Feb 18 '21 at 08:35
  • @JanChristophTerasa I understand your concern now. Thank you for the insight. I have edited my question to point out that my ```dict``` is bijective. – Dionisius Pratama Feb 18 '21 at 08:37
1

There is another solution, which doesn't require to generate an intermediate dictionary with values and keys switched. It just does the same in one step as the solution proposed by @Krishna Chaurasia. Limitations are the same, especially you have to ensure that dic is bijective elsewhere for this to work.

dic = {
    0: 0, 
    30: 1, 
    35: 2, 
    42: 3, 
    53: 4, 
    54: 5, 
    55: 6, 
    81: 7, 
    83: 8, 
    95: 9, 
    99: 10
}

L = [0, 0, 7, 2, 2, 1, 9]

out = [k for el in L for k,v in dic.items() if el==v]

Output

print(out)
# [0, 0, 81, 35, 35, 30, 95]
AnsFourtyTwo
  • 2,480
  • 2
  • 13
  • 33