Question

Imaginez que j'ai ces listes python:

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

Existe-t-il un moyen simple ou au moins simple de produire la liste de dictionnaires suivante?

[
    {'name': 'Monty', 'age': 42},
    {'name': 'Matt',  'age': 28},
    {'name': 'Frank', 'age': 33}
]
Était-ce utile?

La solution

Voici la méthode zip

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

Autres conseils

Ce n'est pas joli, mais voici un one-line utilisant une liste comprenant, zip et un pas à pas:

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

Manière stupide, mais qui me vient immédiatement à l'esprit:

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.

zip fait presque ce que vous voulez; malheureusement, plutôt que de parcourir la liste plus courte, il casse. Peut-être y at-il une fonction connexe qui cycle?

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

/ EDIT: Oh, vous voulez une liste de dict . Les œuvres suivantes (merci également à Peter):

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]))

Dans la réponse, Konrad Rudolph

  

zip fait presque ce que vous voulez; malheureusement, plutôt que de parcourir la liste plus courte, il casse. Peut-être y at-il une fonction connexe qui cycle?

Voici un moyen:

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))]

Je ne l'appellerai pas Pythonic (je pense que c'est trop intelligent), mais c'est peut-être ce que vous recherchez.

Il n'y a aucun avantage à parcourir la liste keys à l'aide de itertools .cycle () , car chaque parcours de clés correspond à la création d'un dictionnaire.

MODIFIER: une autre façon de procéder:

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))]

C’est beaucoup plus pythonique: il existe une fonction utilitaire lisible avec un objectif clair, et le reste du code en découle naturellement.

Voici mon approche simple. Cela semble être proche de l’idée que @Cheery avait sauf que je détruis la liste des entrées.

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

Encore un essai, peut-être plus bête que le premier:

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'}]

Mais c'est à vous de décider s'il est plus bête.

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

UG-LEEE. Je détesterais voir un code qui ressemble à ça. Mais cela semble juste.

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 )

Toujours un peu moche, mais les noms aident à en comprendre le sens.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top