【问题标题】:Python3 Dictionary ComprehensionPython3字典理解
【发布时间】:2020-12-13 23:42:56
【问题描述】:

我很难理解字典。

我有一个字典列表,其中每个字典包含具有不同值的相同键:

  list_of_dictionaries = [{k1:v1, k2:v2}{k1:v3, k2:v4}{k1:v5, k2:v6}, ...]

我想要一个列表字典,其中每个键都有一个值,该值是在字典列表中该键下找到的那些值的列表:

  dictionary_of_lists = {k1:[v1,v3,v5], k2:[v2,v4,v6], ...}

目前,我正在通过手动输入键并使用列表推导来获取值来创建这个单一的综合字典:

dictionary_of_lists = {
   k1:[i[k1] for i in list_of_dictionaries],
   k2:[i[k2] for i in list_of_dictionaries],
   ...
}

只有几个键还不错,但超过 20 个键看起来很乱,重复的代码。我正在努力制定一个可以达到相同结果的字典理解。类似于“对于此列表中的每个字典,将与每个键对应的值添加到由另一个字典中的相同键表示的列表中”?我尝试了 dict.update() 方法,它不允许我将值添加到列表中 - 它会擦除并“更新”已经存在的值。

【问题讨论】:

    标签: python python-3.x dictionary-comprehension


    【解决方案1】:

    请注意每行仅因使用的键而异。这意味着密钥应该被迭代:

    list_of_dictionaries  = [{1: 2, 2: 3}, {1: 4, 2: 5}, {1: 6, 2: 7}]
    
    # Only safe if you know there will always be at least one dictionary
    keys = list_of_dictionaries[0].keys()  
    
    dictionary_of_lists = \
         {k: [i[k] for i in list_of_dictionaries]
          for k in keys}  # A second level of iteration to automate what you were doing manually before
    
    print(dictionary_of_lists)
    >>> {1: [2, 4, 6], 2: [3, 5, 7]}
    

    【讨论】:

    • 喜欢列表理解。如果您不使用变量名作为keys 会更喜欢,因为它可能会与 dict.keys 混淆
    • 很好的解决方案!也可以在一条线上完成,非常理想。 dictionary_of_lists = {k: [i[k] for i in list_of_dictionaries] for k in list of_dictionaries[0].keys()}
    【解决方案2】:

    如果允许您使用 pandas,这是一个更简单的解决方案。

    使用 pandas,您将获得以下结果:

    import pandas as pd
    list_of_dicts = [{'k1':'v1', 'k2':'v2'}, {'k1':'v3', 'k2':'v4'},
                     {'k1':'v5', 'k2':'v6'}, {'k1':'v7', 'k2':'v8'},
                     {'k1':'v9', 'k2':'v10'}]
    df = pd.DataFrame(list_of_dicts)
    k = {c:df[c].tolist() for c in df.columns}
    print (k)
    

    这个输出将是:

    {'k1': ['v1', 'v3', 'v5', 'v7', 'v9'], 'k2': ['v2', 'v4', 'v6', 'v8', 'v10']}
    

    使用这种方法,您可以不断添加任意数量的键,解决方案将是相同的。

    import pandas as pd
    list_of_dicts = [{'k1':'v1' , 'k2':'v2' , 'k3': 'v3'},
                     {'k1':'v4' , 'k2':'v5' , 'k3': 'v6'},
                     {'k1':'v7' , 'k2':'v8' , 'k3': 'v9'},
                     {'k1':'v10', 'k2':'v11', 'k3': 'v12'},
                     {'k1':'v13' ,'k2':'v14', 'k3': 'v15'}]
    df = pd.DataFrame(list_of_dicts)
    k = {c:df[c].tolist() for c in df.columns}
    print (k)
    

    这将导致:

    {'k1': ['v1', 'v4', 'v7', 'v10', 'v13'], 'k2': ['v2', 'v5', 'v8', 'v11', 'v14'], 'k3': ['v3', 'v6', 'v9', 'v12', 'v15']}
    

    唯一的限制是每组 dicts 必须具有相同数量的元素(k1、k2、k3)。您不能拥有 (k1,k2) 和 (k1,k2,k3)。然后代码将中断,因为数据框正在寻找每列相同数量的元素。

    【讨论】:

    • 熊猫当然是被允许的——我本来打算使用列表字典来创建一个DataFrame!这非常有帮助,谢谢。
    • Pandas 让整个过程变得如此之快,并且您获得了更好的灵活性。希望你探索它们。如果这个答案有帮助,别忘了点赞。
    【解决方案3】:

    一个简单的 for 循环就可以解决问题,而且效率很高。
    solution provided 对列表中所有字典的每个键进行迭代。

    >>> from collections import defaultdict
    >>> res = defaultdict(list)
    >>> for d in list_of_dictionaries:
    ...     for k, v in d.items():
    ...             res[k].append(v)
    ... 
    

    【讨论】:

      【解决方案4】:

      使用 Python collections 库:

      from collections import defaultdict
      
      
      list_of_dictionaries = [{'k1': 'v1', 'k2':'v2'},
                              {'k1':'v3', 'k2':'v4'},
                              {'k1':'v5', 'k2':'v6'}]
      
      res = defaultdict(list)
      
      for element in list_of_dictionaries:
          for key, value in  element.items():
              res[key].append(value)
      
      print(dict(res))
      
      out: {'k1': ['v1', 'v3', 'v5'], 'k2': ['v2', 'v4', 'v6']}
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-02-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-30
        • 2021-01-09
        • 2021-07-24
        • 2016-09-03
        相关资源
        最近更新 更多