6

想象一下,我有这些 python 列表:

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

是否有直接或至少简单的方法来生成以下字典列表?

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

8 回答 8

14

这是邮编方式

def mapper(keys, values):
    n = len(keys)
    return [dict(zip(keys, values[i:i + n]))
            for i in range(0, len(values), n)]
于 2008-10-28T19:35:22.387 回答
3

这并不漂亮,但这是一个使用列表理解、压缩和步进的单行:

[dict(zip(keys, a)) for a in zip(values[::2], values[1::2])]
于 2008-10-28T20:09:51.130 回答
2

愚蠢的方式,但我立即想到的一种方式:

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.
于 2008-10-28T19:11:35.820 回答
2

zip几乎可以满足您的需求;不幸的是,它没有循环较短的列表,而是中断了。也许有一个相关的循环功能?

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

/编辑:哦,你想要一个dict列表。以下作品(也感谢彼得):

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]))
于 2008-10-28T19:13:29.543 回答
2

康拉德鲁道夫的回答中

zip 几乎可以满足您的需求;不幸的是,它没有循环较短的列表,而是中断了。也许有一个相关的循环功能?

这里有一个方法:

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

我不会称它为 Pythonic(我认为它太聪明了),但它可能正是我们想要的。

keys使用 循环列表没有任何好处,因为每次遍历 都对应于创建一个字典。itertools.cycle()keys

编辑:这是另一种方式:

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

这更像是pythonic:有一个具有明确目的的可读实用程序函数,其余代码自然地从中流出。

于 2008-10-28T19:55:04.093 回答
1

这是我的简单方法。除了我销毁输入列表之外,这似乎与@Cheery 的想法很接近。

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
于 2008-10-28T19:16:01.800 回答
1

又一次尝试,可能比第一次更愚蠢:

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

但由你决定它是否更愚蠢。

于 2008-10-28T19:28:24.380 回答
0
[dict(zip(keys,values[n:n+len(keys)])) for n in xrange(0,len(values),len(keys)) ]

UG-李。我不想看到看起来像那样的代码。但它看起来是正确的。

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 )

仍然有点难看,但这些名字有助于理解它。

于 2008-10-29T18:25:12.917 回答