230

Let's say I have a list a in Python whose entries conveniently map to a dictionary. Each even element represents the key to the dictionary, and the following odd element is the value

for example,

a = ['hello','world','1','2']

and I'd like to convert it to a dictionary b, where

b['hello'] = 'world'
b['1'] = '2'

What is the syntactically cleanest way to accomplish this?

ninjagecko
  • 88,546
  • 24
  • 137
  • 145
Mike
  • 58,961
  • 76
  • 175
  • 221
  • 4
    Possible duplicate of [Make dictionary from list with python](https://stackoverflow.com/questions/2597166/make-dictionary-from-list-with-python) – Jeru Luke Mar 06 '18 at 08:37

12 Answers12

306
b = dict(zip(a[::2], a[1::2]))

If a is large, you will probably want to do something like the following, which doesn't make any temporary lists like the above.

from itertools import izip
i = iter(a)
b = dict(izip(i, i))

In Python 3 you could also use a dict comprehension, but ironically I think the simplest way to do it will be with range() and len(), which would normally be a code smell.

b = {a[i]: a[i+1] for i in range(0, len(a), 2)}

So the iter()/izip() method is still probably the most Pythonic in Python 3, although as EOL notes in a comment, zip() is already lazy in Python 3 so you don't need izip().

i = iter(a)
b = dict(zip(i, i))

In Python 3.8 and later you can write this on one line using the "walrus" operator (:=):

b = dict(zip(i := iter(a), i))

Otherwise you'd need to use a semicolon to get it on one line.

kindall
  • 178,883
  • 35
  • 278
  • 309
69

Simple answer

Another option (courtesy of Alex Martelli - source):

dict(x[i:i+2] for i in range(0, len(x), 2))

Related note

If you have this:

a = ['bi','double','duo','two']

and you want this (each element of the list keying a given value (2 in this case)):

{'bi':2,'double':2,'duo':2,'two':2}

you can use:

>>> dict((k,2) for k in a)
{'double': 2, 'bi': 2, 'two': 2, 'duo': 2}
wjandrea
  • 28,235
  • 9
  • 60
  • 81
JobJob
  • 3,822
  • 3
  • 33
  • 34
  • 2
    Is this for Python 3 only? – Tagar Jul 02 '15 at 01:18
  • 3
    use `fromkeys`. ```>>> dict.fromkeys(a, 2) {'bi': 2, 'double': 2, 'duo': 2, 'two': 2} ``` – Gdogg Sep 07 '17 at 17:45
  • 2
    This is doing something else than what the question is asking. – ozn Aug 29 '18 at 22:32
  • for some reason `dict.fromkeys()` is making every key's value to be duplicated ( like the items i gave are all "linked" or pointing to the same place in memory ) try: `a = dict.fromkeys(['op1', 'op2'], {})` and then `a["op1"] = 3` you'll see that also `a["op2"]` was populated – Ricky Levi Nov 29 '21 at 19:56
19

You can use a dict comprehension for this pretty easily:

a = ['hello','world','1','2']

my_dict = {item : a[index+1] for index, item in enumerate(a) if index % 2 == 0}

This is equivalent to the for loop below:

my_dict = {}
for index, item in enumerate(a):
    if index % 2 == 0:
        my_dict[item] = a[index+1]
Chris Arena
  • 1,602
  • 15
  • 17
17

Something i find pretty cool, which is that if your list is only 2 items long:

ls = ['a', 'b']
dict([ls])
>>> {'a':'b'}

Remember, dict accepts any iterable containing an iterable where each item in the iterable must itself be an iterable with exactly two objects.

rix
  • 10,104
  • 14
  • 65
  • 92
  • quick and simple one, just to add if the list contains more than two items then use dict(ls) instead of dict([ls]). for e.g. if ls=['a', 'b', 'c', 'd'] then dict(ls) – ankit tyagi May 21 '17 at 11:09
  • 2
    Nice & sleek. **'each item in the iterable must itself be an iterable with exactly two objects.'** is the key fact here. – Abhijeet Jun 22 '18 at 09:34
  • This really deserves more upvotes, half the answers above are the same and just say to use zip... – Mark May 01 '21 at 15:43
5

May not be the most pythonic, but

>>> b = {}
>>> for i in range(0, len(a), 2):
        b[a[i]] = a[i+1]
sahhhm
  • 5,325
  • 2
  • 27
  • 22
  • 10
    read about [`enumerate`](http://docs.python.org/library/functions.html#enumerate) – SilentGhost Jan 01 '11 at 22:34
  • 5
    enumerate doesn't let you specify a step size, but you could use `for i, key in enumerate(a[::2]):`. Still unpythonic since the dict constructor can do most of the work here for you – John La Rooy Jan 01 '11 at 22:42
  • @SilentGhost, gnibbler: thanks so much for broadening my horizons! I'll be sure to incorporate it as much as possible in the future! – sahhhm Jan 01 '11 at 23:35
  • @gnibbler: Could you explain a little more about how the `for i, key in enumerate(a[::2]):` approach might work? The resulting pair values would be `0 hello` and `1 1`, and it's unclear to me how to use them to produce `{'hello':'world', '1':'2'}`. – martineau Jan 29 '11 at 14:59
  • 1
    @martineau, you are correct. I think i must have meant `enumerate(a)[::2]` – John La Rooy Jan 29 '11 at 22:32
4

You can do it pretty fast without creating extra arrays, so this will work even for very large arrays:

dict(izip(*([iter(a)]*2)))

If you have a generator a, even better:

dict(izip(*([a]*2)))

Here's the rundown:

iter(h)    #create an iterator from the array, no copies here
[]*2       #creates an array with two copies of the same iterator, the trick
izip(*())  #consumes the two iterators creating a tuple
dict()     #puts the tuples into key,value of the dictionary
topkara
  • 886
  • 9
  • 15
  • this will make a dictionary with equal key and value pairs (`{'hello':'hello','world':'world','1':'1','2':'2'}`) – mik Apr 16 '18 at 15:29
  • Nope, all work just fine. Please read more carefully. It says: "If you have a generator a..." If you don't have a generator, just use the first line. The second one is an alternative that would be useful if you have a generator instead of a list, as one would most of the time. – topkara Apr 19 '18 at 01:32
1

You can also do it like this (string to list conversion here, then conversion to a dictionary)

    string_list = """
    Hello World
    Goodbye Night
    Great Day
    Final Sunset
    """.split()

    string_list = dict(zip(string_list[::2],string_list[1::2]))

    print string_list
Stefan Gruenwald
  • 2,582
  • 24
  • 30
1

I am also very much interested to have a one-liner for this conversion, as far such a list is the default initializer for hashed in Perl.

Exceptionally comprehensive answer is given in this thread -

Mine one I am newbie in Python), using Python 2.7 Generator Expressions, would be:

dict((a[i], a[i + 1]) for i in range(0, len(a) - 1, 2))

Community
  • 1
  • 1
Oleksiy
  • 91
  • 1
  • 6
0

I am not sure if this is pythonic, but seems to work

def alternate_list(a):
   return a[::2], a[1::2]

key_list,value_list = alternate_list(a)
b = dict(zip(key_list,value_list))
Manu
  • 728
  • 7
  • 12
0

try below code:

  >>> d2 = dict([('one',1), ('two', 2), ('three', 3)])
  >>> d2
      {'three': 3, 'two': 2, 'one': 1}
Joey Harwood
  • 961
  • 1
  • 17
  • 27
muhammed
  • 39
  • 6
0

You can also try this approach save the keys and values in different list and then use dict method

data=['test1', '1', 'test2', '2', 'test3', '3', 'test4', '4']

keys=[]
values=[]
for i,j in enumerate(data):
    if i%2==0:
        keys.append(j)
    else:
        values.append(j)

print(dict(zip(keys,values)))

output:

{'test3': '3', 'test1': '1', 'test2': '2', 'test4': '4'}
Aaditya Ura
  • 12,007
  • 7
  • 50
  • 88
0
{x: a[a.index(x)+1] for x in a if a.index(x) % 2 ==0}

result : {'hello': 'world', '1': '2'}
Mahdi Ghelichi
  • 1,090
  • 14
  • 23