【问题标题】:Map two lists into one single list of dictionaries将两个列表映射到一个字典列表
【发布时间】:2010-09-19 15:44:02
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: python dictionary list


    【解决方案1】:

    这是邮编方式

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

    【讨论】:

    • 使用 l(小写 ell)作为变量名是致命的 pep8 违规。特此撤销您的 Pythoning 许可证! ;)
    • 使用 zip 和切片运算符的 step 部分将这一切放入一个列表理解中: [dict(zip(keys, a)) for a in zip(values[::2], values [1::2])]
    • @jblocksom:它只是一个列表理解。您的方式不考虑更多(或更少)然后两个键。 @ddaa: :P @guido: 乐于助人
    • 我更改了代码格式。这是一个口味问题,因此请随时回滚更改。
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

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

      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.
      

      【讨论】:

      • 这实际上并没有创建列表,只是产生了元素。
      • 只要使用list(fields_from_list(keys, values))
      【解决方案4】:

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

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

      /EDIT:哦,你想要一个 dictlist。以下作品(也感谢彼得):

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

      【讨论】:

      • 你说得对,一个类似 zip 的循环函数就可以了。
      • itertools.cycle 将重复一个序列。所以dict(zip(itertools.cycle(keys), values)) 应该这样做。
      • 彼得,谢谢,但我刚刚尝试过,但没有成功。它返回 {'age': 33, 'name': 'Frank'}
      【解决方案5】:

      Konrad Rudolph的回答中

      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(我认为它太聪明了),但它可能是我们正在寻找的东西。

      使用itertools.cycle() 循环keys 列表没有任何好处,因为每次遍历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:有一个具有明确目的的可读实用程序函数,其余代码自然地从中流出。

      【讨论】:

      • 我已更改 '/' -> '//'。因此代码变成了 Python 3.0 和 from __future__ import division 兼容。
      【解决方案6】:

      这是我的简单方法。除了我销毁输入列表之外,这似乎与@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
      

      【讨论】:

        【解决方案7】:

        再试一次,可能比第一次更笨:

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

        但是否更笨由您决定。

        【讨论】:

          【解决方案8】:
          [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 )
          

          还是有点难看,但名字有助于理解它。

          【讨论】:

            猜你喜欢
            • 2012-09-17
            • 1970-01-01
            • 2011-05-01
            • 2021-12-11
            • 2020-03-30
            • 2010-12-31
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多