66

I am newbie to Python and need to convert a list to dictionary. I know that we can convert a list of tuples to a dictionary.

This is the input list:

L = [1,term1, 3, term2, x, term3,... z, termN]

and I want to convert this list to a list of tuples (or directly to a dictionary) like this:

[(1, term1), (3, term2), (x, term3), ...(z, termN)]

How can we do that easily in Python?

kaya3
  • 47,440
  • 4
  • 68
  • 97

7 Answers7

135
>>> L = [1, "term1", 3, "term2", 4, "term3", 5, "termN"]
# Create an iterator
>>> it = iter(L)
# zip the iterator with itself
>>> zip(it, it)
[(1, 'term1'), (3, 'term2'), (4, 'term3'), (5, 'termN')]

You want to group three items at a time?

>>> zip(it, it, it)

You want to group N items at a time?

# Create N copies of the same iterator
it = [iter(L)] * N
# Unpack the copies of the iterator, and pass them as parameters to zip
>>> zip(*it)
thefourtheye
  • 233,700
  • 52
  • 457
  • 497
  • 2
    Could someone explain what `zip` is doing in this context? I thought I understood how it works but apparently not, since this doesn't give `[(1,1,1),('term1','term1','term1'),...]` – user1717828 Aug 11 '17 at 19:37
  • 9
    @user1717828 every time you access the iterator it advances the position. Zip is pairing two things, taken from the same iterator here. If you wrote `zip(iter(L), iter(L), iter(L))` it would do that, but by breaking out the iter creation and sharing it you get this behaviour. – Flexo Aug 25 '17 at 13:47
  • 5
    This will work in python2, but in python3, you actually need to put the `zip` object in a `list` like so: `list(zip(it,it))` as python3 does not evaluate the `zip` unless you explicitly ask for it - see https://stackoverflow.com/a/19777642 – Mani Jul 16 '20 at 05:57
  • wow, at first didn't understand what you did there, but now I'm amazed at how simple and beautiful your solution is – winwin Oct 21 '21 at 19:32
  • Well, `zip` internally / implicit converts `list` to `iter` and using `next` on it? – Давид Шико Dec 16 '22 at 13:32
18

Try with the group clustering idiom:

zip(*[iter(L)]*2)

From https://docs.python.org/2/library/functions.html:

The left-to-right evaluation order of the iterables is guaranteed. This makes possible an idiom for clustering a data series into n-length groups using zip(*[iter(s)]*n).

  • Ok, I think I understood your code, It is same as @thefourtheye's answer except you use `* 2` to make two copies. I can also write is as `zip(*(iter(L),) * 2)`. – Grijesh Chauhan Apr 25 '14 at 07:12
  • @GrijeshChauhan Yes, it is a shortened form of the same solution – Pablo Francisco Pérez Hidalgo Apr 25 '14 at 07:15
  • Thanks, its very interesting that your code is just 17 bytes long :) – Grijesh Chauhan Apr 25 '14 at 07:19
  • Very elegant and idiomatic solution. Thanks! – Pavel Razgovorov May 13 '20 at 21:08
  • "The left-to-right evaluation order of the iterables is guaranteed" upvote for the explanation quote.. I finally get how this works despite using it many times!! each time the iterator is "evaluated" it is "advanced" to the next element. Thats how/why we get the next element as the second element of the tuple. It's so obvious now! – Kai Jun 02 '20 at 21:27
12

List directly into a dictionary using zip to pair consecutive even and odd elements:

m = [ 1, 2, 3, 4, 5, 6, 7, 8 ] 
d = { x : y for x, y in zip(m[::2], m[1::2]) }

or, since you are familiar with the tuple -> dict direction:

d = dict(t for t in zip(m[::2], m[1::2]))

even:

d = dict(zip(m[::2], m[1::2]))
perreal
  • 94,503
  • 21
  • 155
  • 181
9

Using slicing?

L = [1, "term1", 2, "term2", 3, "term3"]
L = zip(L[::2], L[1::2])

print L
velis
  • 8,747
  • 4
  • 44
  • 64
5

Try this ,

>>> L = [1, "term1", 3, "term2", 4, "term3", 5, "termN"]
>>> it = iter(L)
>>> [(x, next(it)) for x in it ]
[(1, 'term1'), (3, 'term2'), (4, 'term3'), (5, 'termN')]
>>> 

OR

>>> L = [1, "term1", 3, "term2", 4, "term3", 5, "termN"]
>>> [i for i in zip(*[iter(L)]*2)]
[(1, 'term1'), (3, 'term2'), (4, 'term3'), (5, 'termN')]

OR

>>> L = [1, "term1", 3, "term2", 4, "term3", 5, "termN"]
>>> map(None,*[iter(L)]*2)
[(1, 'term1'), (3, 'term2'), (4, 'term3'), (5, 'termN')]
>>> 
Nishant Nawarkhede
  • 8,234
  • 12
  • 59
  • 81
4
[(L[i], L[i+1]) for i in xrange(0, len(L), 2)]
Xing Fei
  • 287
  • 1
  • 6
  • Hey getting, `Traceback (most recent call last): File "ab.py", line 105, in print [(L[i], L[i+1]) for i in xrange(0, len(L), 2)] IndexError: list index out of range` –  Apr 25 '14 at 07:10
  • @trex you are trying with odd length `L`, according to your question I think you should have even length `L` this will work on Python2.X in Python3.x you should use range instead of xrange – Grijesh Chauhan Apr 25 '14 at 07:22
  • @GrijeshChauhan I am using python2.7, so I use xrange. in python2, xrange is a generator and range returns a list. for a big number n, python2's range(n) will consume many memory. In python3, range is the generator, and xrange no more exists. – Xing Fei Apr 25 '14 at 07:29
  • XingFei yes I understand the issue I just means to respond @trex to suggest how to make it execute without error. – Grijesh Chauhan Apr 25 '14 at 07:31
2

The below code will take care of both even and odd sized list :

[set(L[i:i+2]) for i in range(0, len(L),2)]
Sahil Chhabra
  • 10,621
  • 4
  • 63
  • 62