125

I am trying to convert the following list:

l = ['A', 'B', 'C']

To a dictionary like:

d = {'A': 0, 'B': 1, 'C': 2}

I have tried answers from other posts but none is working for me. I have the following code for now:

d = {l[i]: i for i in range(len(l))}

Which gives me this error:

unhashable type: 'list'
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
ahajib
  • 12,838
  • 29
  • 79
  • 120
  • your code works for me. – Daniel Apr 06 '16 at 18:57
  • 6
    1. Don't use `list` as variable name 2. Use `enumerate` as shown `{j:i for i,j in enumerate(l)}` – Bhargav Rao Apr 06 '16 at 18:57
  • 1
    You have a bug in code you haven't shown us. The elements of `list` are probably lists, although you could have made other mistakes, like writing `list: i` instead of `list[i]: i`. – user2357112 Apr 06 '16 at 19:01
  • @user2357112 I edited the post. You are correct that makes a lot of difference. – ahajib Apr 06 '16 at 19:03
  • Strange that no one noticed what if there are duplicate elements – EXODIA Oct 31 '20 at 08:36
  • For the case where the values repeat, see [this question](https://stackoverflow.com/questions/70199627/most-efficient-way-to-reduce-list-to-map) for creating a list of indexes as values – Tomerikoo Dec 02 '21 at 13:23

7 Answers7

184

You can get the indices of a list from the built-in enumerate. You just need to reverse the index-value map and use a dictionary comprehension to create a dictionary:

>>> lst = ['A', 'B', 'C']
>>> {k: v for v, k in enumerate(lst)}
{'A': 0, 'C': 2, 'B': 1}
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
Abhijit
  • 62,056
  • 18
  • 131
  • 204
  • 3
    When using this solution, be aware that duplicates in the original list will result in a single key with the highest value available. – Mr. Lance E Sloan Aug 26 '22 at 16:36
35

Use built-in functions dict and zip:

>>> lst = ['A', 'B', 'C']
>>> dict(zip(lst, range(len(lst))))
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
florex
  • 943
  • 7
  • 9
11

You can also take advantage of enumerate:

your_list = ['A', 'B', 'C']
your_dict = {key: i for i, key in enumerate(your_list)}
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
gr1zzly be4r
  • 2,072
  • 1
  • 18
  • 33
10

Python dict constructor has an ability to convert list of tuple to dict, with key as first element of tuple and value as second element of tuple. To achieve this you can use builtin function enumerate which yield tuple of (index, value).

However question's requirement is exact opposite i.e. tuple should be (value, index). So this requires and additional step to reverse the tuple elements before passing to dict constructor. For this step we can use builtin reversed and apply it to each element of list using map

>>> lst = ['A', 'B', 'C']
>>> dict(map(reversed, enumerate(lst)))
>>> {'A': 0, 'C': 2, 'B': 1}
jpp
  • 159,742
  • 34
  • 281
  • 339
Sohaib Farooqi
  • 5,457
  • 4
  • 31
  • 43
  • 1
    This version seems to take longer than the other solutions provided – Leland Hepworth Aug 12 '20 at 16:12
  • A short solution is nice, but at a cursory glance, it's not clear how `reversed()` is being used. Because of the extra function calls to `map()` and `reversed()`, it also runs slower than a dictionary comprehension. – Mr. Lance E Sloan Aug 26 '22 at 16:29
3
  1. If the elements in target list are unique, then a dict comprehension should be enough and elegant, just like the accepted answer.

    >>> lst = ['A', 'B', 'C']
    >>> pos_map = {ele: pos for pos, ele in enumerate(lst)}
    
  2. But if there were duplicated elements in target list, then we could use the handy defaultdict in collections module:

    >>> lst = ['A', 'B', 'C', 'A', 'A', 'B']
    >>> from collections import defaultdict
    >>> pos_map = defaultdict(list)
    >>> for pos, ele in enumerate(lst):
    >>>     pos_map[ele].append(pos)
    >>>
    >>> pos_map
    >>> defaultdict(list, {'A': [0, 3, 4], 'B': [1, 5], 'C': [2]})
    
YaOzI
  • 16,128
  • 9
  • 76
  • 72
0

You have to convert the unhashable list into a tuple:

dct = {tuple(key): idx for idx, key in enumerate(lst)}
Daniel
  • 42,087
  • 4
  • 55
  • 81
0

The easiest solution I used was:

lst = list('ABC')
dict(enumerate(lst))

edit: This is the reverse of what the author needed and exactly what I needed

  • 3
    This will give you {0: 'A', 1: 'B', 2: 'C'} which is different from the wanted result {'A':0, 'B':1, 'C':2} – MadMike Apr 19 '21 at 07:03
  • 1
    Which is also really not necessary. Why have a dict whose keys are sequential integers? It is just a list for all purposes... – Tomerikoo Dec 02 '21 at 13:36