【问题标题】:How to create a list of dictionaries from a dictionary with lists of different lengths如何从具有不同长度列表的字典中创建字典列表
【发布时间】:2020-01-11 00:50:40
【问题描述】:

我想从每个列表中创建一个具有相同索引元素的字典列表。

我有这本词典:

d = {'name': ['bob', 'john', 'harry', 'mary'], 
     'age': [13, 19, 23], 
     'height': [164, 188], 
     'job': ['programmer']}

想要的输出是:

d2 = [{'name': 'bob', 'age': 13, 'height': 164, 'job': 'programmer'}, 
      {'name': 'john', 'age': 19, 'height': 188}, 
      {'name': 'harry', 'age': 23},
      {'name': 'mary'}]

我尝试过这样的事情:

d2 = [dict(zip(d, t)) for t in zip(*d.values())]

但我的输出是:

d2 = [{'name': 'bob', 'age': 13, 'height': 164, 'job': 'programmer'}]

我认为这是因为列表的长度不同。

【问题讨论】:

    标签: python dictionary list-comprehension itertools


    【解决方案1】:

    您可以使用itertools.zip_longest 并过滤掉None 值:

    from itertools import zip_longest
    
    [{x: y for x, y in zip(d, t) if y is not None} for t in zip_longest(*d.values())]
    # [{'name': 'bob', 'age': 13, 'height': 164, 'job': 'programmer'}, 
    #  {'name': 'john', 'age': 19, 'height': 188}, 
    #  {'name': 'harry', 'age': 23}, 
    #  {'name': 'mary'}]
    

    【讨论】:

      【解决方案2】:

      您可以在这里使用zip_longest

      from itertools import zip_longest
      
      keys = d.keys()
      
      d2 = [
          {k: v for k, v in zip(keys, vs) if v is not None}
          for vs in zip_longest(*d.values())
      ]

      如果值也可以是None,我们可以通过使用虚拟值来规避它:

      from itertools import zip_longest
      
      keys = d.keys()
      dummy = object()
      
      d2 = [
          {k: v for k, v in zip(keys, vs) if v is not dummy}
          for vs in zip_longest(*d.values(), fillvalue=dummy)
      ]

      这里的 dummy 是一个对象,我们确信它不属于 d 中的项目(因为我们在构造 d 之后构造它)。通过使用is 比较,我们可以知道该值是否是“填充值”。

      这会给我们:

      >>> d2
      [{'name': 'bob', 'age': 13, 'height': 164, 'job': 'programmer'}, {'name': 'john', 'age': 19, 'height': 188}, {'name': 'harry', 'age': 23}, {'name': 'mary'}]
      

      【讨论】:

        【解决方案3】:

        这是另一种方法:

        d = {'name': ['bob', 'john', 'harry', 'mary'], 'age': [13, 19, 23], 'height': [164, 188], 'job': ['programmer']}
        m = max(map(len, d.values()))
        d1 = {k : (v if len(v)==m else v+['']*(m-len(v))) for k,v in d.items()}
        d2 = [{k:v for k,v in zip(d, t) if v} for t in zip(*d1.values())]
        print(d2)
        

        输出

        [{'height': 164, 'age': 13, 'job': 'programmer', 'name': 'bob'}, {'height': 188, 'age': 19, 'name': 'john'}, {'age': 23, 'name': 'harry'}, {'name': 'mary'}]
        

        【讨论】:

          【解决方案4】:

          一个不使用 zip_longest 的简单解决方案,记录一下:

          d = {'name': ['bob', 'john', 'harry', 'mary'], 'age': [13, 19, 23], 'height': [164, 188], 'job': ['programmer']}
          
          recordset = [{k: v[i] for k, v in d.items() if i < len(v)} for i in range(max([len(l) for l in d.values()]))]
          
          print(recordset)  # >> [{'name': 'bob', 'age': 13, 'height': 164, 'job': 'programmer'}, 
                                  {'name': 'john', 'age': 19, 'height': 188}, 
                                  {'name': 'harry', 'age': 23}, 
                                  {'name': 'mary'}]
          

          【讨论】:

            【解决方案5】:

            只需保留所有内容并添加此导入语句:

            从 itertools 导入 zip_longest 为 zip

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2021-07-03
              • 2023-02-05
              • 2018-09-15
              • 2018-07-25
              • 1970-01-01
              • 2019-03-20
              • 2018-11-06
              • 2021-03-01
              相关资源
              最近更新 更多