12

I have a dictionary in python 2.7 that has the following structure:

x = {
     '1': ['a', 'b', 'c'],
     '2': ['d', 'e', 'f']
    }

The length of the value list is always the same and I would like to basically zip the value lists with corresponding values. So, in this case it will create three new lists as:

[['a', 'd'], ['b', 'e'], ['c', 'f']]

I know I can write an awful looking loop to do this but I was wondering if there is a more pythonic way to do this. I need to preserve the order.

Luca
  • 10,458
  • 24
  • 107
  • 234

3 Answers3

19

You can do the following:

zip(*x.values())

Explanation:

  • x.values() returns [['a', 'b', 'c'], ['d', 'e', 'f']] (order may change so you might need to sort x first.)
  • zip([a, b], [c, d]) returns [[a, c], [b, d]]
  • To expand x.values() into arguments to zip, prepend * to it.
Ozgur Vatansever
  • 49,246
  • 17
  • 84
  • 119
  • 4
    That doesn't have a defined order. It may produce `[['a', 'd'], ...]` or `[['d', 'a'], ...]`. – Dan D. Nov 17 '16 at 15:31
  • 2
    @DanD. if you want it by key order: `zip(*list(zip(*sorted(x.items())))[1])` – Patrick Haugh Nov 17 '16 at 15:39
  • While not the OP's question, there are cases where you want to avoid nested lists. For those, I suggest using `list(itertools.chain(*x.values()))` to flatten the returned list – Addison Klinke Sep 13 '19 at 13:21
2

This is single line solves the problem but is likely worse looking than your loop. It loops over the sorted keys and produces a list to pass to zip and then maps over the result converting the tuples into lists.

>>> x = {'1': ['a', 'b', 'c'], '2': ['d', 'e', 'f']}
>>> map(list, zip(*[x[k] for k in sorted(x)]))
[['a', 'd'], ['b', 'e'], ['c', 'f']]
Dan D.
  • 73,243
  • 15
  • 104
  • 123
-1
res = list(zip(x['1'], x['2']))
res = list(map(list, res))

An explanation:

zip(x['1'], x['2'])

Creates a zip object that links up your pairs.

res = list(zip(x['1'], x['2']))

That zip object now become a list of tuples.

list(map(list, res))

For each element in res (each tuple), change the data structure from tuple to list, as you requested in your desired output above (map the list data type onto all elements in res). Then, convert that map object into a list to arrive at the final, desired result.

blacksite
  • 12,086
  • 10
  • 64
  • 109
  • Any reason this doesn't work, those who downvoted? It literally gives the output OP showed above. – blacksite Nov 17 '16 at 15:34
  • 4
    You had to hard-code the keys? – OneCricketeer Nov 17 '16 at 15:35
  • 2
    While this code snippet may solve the question, including an explanation [really helps](http://meta.stackexchange.com/q/114762) to improve the quality of your post. Remember that you are answering the question for readers in the future, not just the person asking now! Please [edit] your answer to add explanation, and give an indication of what limitations and assumptions apply. – BrokenBinary Nov 17 '16 at 17:29
  • See above for an explanation. – blacksite Nov 17 '16 at 18:08