Guido
Guido

Reputation: 47705

Map two lists into one single list of dictionaries

Imagine I have these python lists:

keys = ['name', 'age']
values = ['Monty', 42, 'Matt', 28, 'Frank', 33]

Is there a direct or at least a simple way to produce the following list of dictionaries ?

[
    {'name': 'Monty', 'age': 42},
    {'name': 'Matt',  'age': 28},
    {'name': 'Frank', 'age': 33}
]

Upvotes: 6

Views: 2138

Answers (8)

ddaa
ddaa

Reputation: 54544

In the answer by Konrad Rudolph

zip nearly does what you want; unfortunately, rather than cycling the shorter list, it breaks. Perhaps there's a related function that cycles?

Here's a way:

keys = ['name', 'age']
values = ['Monty', 42, 'Matt', 28, 'Frank', 33]
iter_values = iter(values)
[dict(zip(keys, iter_values)) for _ in range(len(values) // len(keys))]

I will not call it Pythonic (I think it's too clever), but it might be what are looking for.

There is no benefit in cycling the keys list using itertools.cycle(), because each traversal of keys corresponds to the creation of one dictionnary.

EDIT: Here's another way:

def iter_cut(seq, size):
    for i in range(len(seq) / size):
        yield seq[i*size:(i+1)*size]

keys = ['name', 'age']
values = ['Monty', 42, 'Matt', 28, 'Frank', 33]
[dict(zip(keys, some_values)) for some_values in iter_cut(values, len(keys))]

This is much more pythonic: there's a readable utility function with a clear purpose, and the rest of the code flows naturally from it.

Upvotes: 2

Toni Ruža
Toni Ruža

Reputation: 7512

Here is the zip way

def mapper(keys, values):
    n = len(keys)
    return [dict(zip(keys, values[i:i + n]))
            for i in range(0, len(values), n)]

Upvotes: 14

Tim Ottinger
Tim Ottinger

Reputation: 1452

[dict(zip(keys,values[n:n+len(keys)])) for n in xrange(0,len(values),len(keys)) ]

UG-LEEE. I'd hate to see code that looks like that. But it looks right.

def dictizer(keys, values):
   steps = xrange(0,len(values),len(keys))
   bites = ( values[n:n+len(keys)] for n in steps)
   return ( dict(zip(keys,bite)) for bite in bites )

Still a little ugly, but the names help make sense of it.

Upvotes: 0

Konrad Rudolph
Konrad Rudolph

Reputation: 546183

zip nearly does what you want; unfortunately, rather than cycling the shorter list, it breaks. Perhaps there's a related function that cycles?

$ python
>>> keys = ['name', 'age']
>>> values = ['Monty', 42, 'Matt', 28, 'Frank', 33]
>>> dict(zip(keys, values))
{'age': 42, 'name': 'Monty'}

/EDIT: Oh, you want a list of dict. The following works (thanks to Peter, as well):

from itertoos import cycle

keys = ['name', 'age']
values = ['Monty', 42, 'Matt', 28, 'Frank', 33]

x = zip(cycle(keys), values)
map(lambda a: dict(a), zip(x[::2], x[1::2]))

Upvotes: 2

jblocksom
jblocksom

Reputation: 14505

It's not pretty but here's a one-liner using a list comprehension, zip and stepping:

[dict(zip(keys, a)) for a in zip(values[::2], values[1::2])]

Upvotes: 3

Cheery
Cheery

Reputation: 25463

Dumb way, but one that comes immediately to my mind:

def fields_from_list(keys, values):
    iterator = iter(values)
    while True:
        yield dict((key, iterator.next()) for key in keys)

list(fields_from_list(keys, values)) # to produce a list.

Upvotes: 2

Cheery
Cheery

Reputation: 25463

Yet another try, perhaps dumber than the first one:

def split_seq(seq, count):
    i = iter(seq)
    while True:
        yield [i.next() for _ in xrange(count)]

>>> [dict(zip(keys, rec)) for rec in split_seq(values, len(keys))]
[{'age': 42, 'name': 'Monty'},
 {'age': 28, 'name': 'Matt'},
 {'age': 33, 'name': 'Frank'}]

But it's up to you to decide whether it's dumber.

Upvotes: 1

David Locke
David Locke

Reputation: 18084

Here's my simple approach. It seems to be close to the idea that @Cheery had except that I destroy the input list.

def pack(keys, values):
  """This function destructively creates a list of dictionaries from the input lists."""
  retval = []
  while values:
    d = {}
    for x in keys:
      d[x] = values.pop(0)
    retval.append(d)
  return retval

Upvotes: 1

Related Questions