Pergunta

Imagine que eu tenha estas listas Python:

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

Existe uma direta ou pelo menos uma maneira simples de produzir a seguinte lista de dicionários?

[
    {'name': 'Monty', 'age': 42},
    {'name': 'Matt',  'age': 28},
    {'name': 'Frank', 'age': 33}
]
Foi útil?

Solução

Aqui é a maneira zip

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

Outras dicas

Não é bonito, mas aqui está uma frase usando uma compreensão da lista, zip e stepping:

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

forma mudo, mas aquele que vem imediatamente à minha mente:

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 quase faz o que quiser; Infelizmente, em vez de andar de bicicleta a lista mais curta, ele quebra. Talvez haja uma função relacionada que os ciclos?

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

/ EDIT: Ah, você quer um lista de dict . As seguintes obras (graças a Peter, bem):

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

Na resposta por Konrad Rudolph

zip quase faz o que quiser; Infelizmente, em vez de andar de bicicleta a lista mais curta, ele quebra. Talvez haja uma função relacionada que os ciclos?

Aqui está uma maneira:

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

Eu não vou chamá-lo Pythonic (eu acho que é muito inteligente), mas pode ser o que está procurando.

Não há nenhum benefício no ciclismo a lista keys usando itertools .cycle() , porque cada travessia de corresponde keys à criação de um Dictionnary.

EDIT: Aqui está outra maneira:

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

Este é muito mais Python:. Há uma função de utilidade legível com um propósito claro, eo resto do código flui naturalmente a partir dele

Aqui está a minha abordagem simples. Parece ser perto da idéia de que @Cheery teve exceto que eu destruir a lista de entrada.

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

No entanto, outra tentativa, talvez mais burro do que o primeiro:

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

Mas cabe a você decidir se é mais burro.

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

UG-Leee. Eu odiaria ver o código que se parece com isso. Mas parece certo.

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 )

Ainda um pouco feio, mas a nomes ajudar a fazer sentido do mesmo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top