【问题标题】:Compare only certain dictionary key values within list of dictionaries Python仅比较字典列表中的某些字典键值 Python
【发布时间】:2021-04-18 05:27:18
【问题描述】:

我有 300k+ 个来自 API 调用的单独字典,格式为:(1 个 API 调用将返回 1 个字典,因此以下每个字典都是成功连续 API 调用的结果,并且在每次 API 调用之后,代码都需要运行返回的字典)

{'N.': 'Sam', 'Batch': 2019, 'Sem': 'I', 'Sub': 'CAD', 'Files': 21, 'Type': 'dwg', 'Size(MB)': 98, 'uid': 732854}
{'N.': 'Sam', 'Batch': 2019, 'Sem': 'I', 'Sub': 'CAD', 'Files': 8, 'Type': 'pdf', 'Size(MB)': 42, 'uid': 735554}
{'N.': 'Sam', 'Batch': 2019, 'Sem': 'I', 'Sub': 'CAD', 'Files': 16, 'Type': 'docx', 'Size(MB)': 104, 'uid': 746748}
{'N.': 'Sam', 'Batch': 2019, 'Sem': 'I', 'Sub': 'CAD', 'Files': 8, 'Type': 'pptx', 'Size(MB)': 57, 'uid': 731024}
{'N.': 'Sam', 'Batch': 2019, 'Sem': 'I', 'Sub': 'CAM', 'Files': 8, 'Type': 'dwg', 'Size(MB)': 71, 'uid': 737328}
{'N.': 'Sam', 'Batch': 2019, 'Sem': 'I', 'Sub': 'CAM', 'Files': 8, 'Type': 'docx', 'Size(MB)': 22, 'uid': 376494}
{'N.': 'Sam', 'Batch': 2019, 'Sem': 'I', 'Sub': 'MIM', 'Files': 8, 'Type': 'pptx', 'Size(MB)': 28, 'uid': 687281}
{'N.': 'Sam', 'Batch': 2019, 'Sem': 'I', 'Sub': 'MIM', 'Files': 8, 'Type': 'docx', 'Size(MB)': 20, 'uid': 687231}
{'N.': 'Sam', 'Batch': 2019, 'Sem': 'I', 'Sub': 'MET', 'Files': 20, 'Type': 'pptx', 'Size(MB)': 204, 'uid': 457281}

我必须将上述单个词典附加到具有以下条件的词典列表中:

  1. dwg、pdf、bmp 是首选“类型”
  2. docx、pptx、xlsx 不是首选,仅在不存在上述任何格式时才考虑
  3. (N.) 名称、批次、Sem、(Sub) 主题、文件、大小可以是任何值,所有 dict 为同一个 ['N.','Batch','Sem','Sub'] 集因此,在各自的 API 调用中一个接一个地返回。
  4. uid 是每个字典的唯一编号。从不重复。
  5. 条目是相同的 ['N.','Batch','Sem','Sub'] 集。因此,如果最终列表中已经有任何条目(例如,如果已经有任何带有 docx/dwg/pdf/bmp 的条目,则具有非首选“类型”作为值的单个 dict存在,pptx不应该出现,)
  6. “类型”中没有首选和非首选的层次结构。例如:如果存在带有 pptx 的条目,则不应出现带有 docx 的另一个条目
  7. 最初列表为空。

因此,在上述数据中,只有以下数据才能进入最终列表:

[{'N.': 'Sam', 'Batch': 2019, 'Sem': 'I', 'Sub': 'CAD', 'Files': 21, 'Type': 'dwg', 'Size(MB)': 98, 'uid': 732854},
{'N.': 'Sam', 'Batch': 2019, 'Sem': 'I', 'Sub': 'CAD', 'Files': 8, 'Type': 'pdf', 'Size(MB)': 42, 'uid': 735554},
{'N.': 'Sam', 'Batch': 2019, 'Sem': 'I', 'Sub': 'CAM', 'Files': 8, 'Type': 'dwg', 'Size(MB)': 71, 'uid': 737328},
{'N.': 'Sam', 'Batch': 2019, 'Sem': 'I', 'Sub': 'MIM', 'Files': 8, 'Type': 'pptx', 'Size(MB)': 28, 'uid': 687281},
{'N.': 'Sam', 'Batch': 2019, 'Sem': 'I', 'Sub': 'MET', 'Files': 20, 'Type': 'pptx', 'Size(MB)': 204, 'uid': 457281},
...]

我尝试使用的代码:

list = []
dict = {'N.': name, 'Batch': year, 'Sem': semester, 'Sub': subject, 'Files': nofiles, 'Type': format, 'Size(MB)': size, 'uid': uniqueid}
comparekeys = ['N.','Batch','Sem','Sub']
nptype = ['docx', 'pptx', 'xlsx']
if dict not in list and format in nptype:
   for key in comparekeys:
      if dict[key] == (item[key] for item in list):
         break
list.append(dict)

上面的代码还附加了非首选格式,如果列表中已存在条目,则无法查找。我也尝试过使用 zip()、set()、.keys(),但无法制定正确的代码。

【问题讨论】:

    标签: python list dictionary search set


    【解决方案1】:

    您说在 API 调用中,相同 ['N.','Batch','Sem','Sub'] 集的所有 dict 一个接一个地连续返回。所以我假设它们是组合在一起的。

    使用itertools.groupby() 处理每组字典。对于每个组,对它们进行排序,以便首选类型在非首选类型之前。然后第一个排序的字典总是被添加到结果中,因为它要么是首选类型,要么没有任何首选类型。在剩余的排序字典中,只有具有首选类型的字典才会附加到结果中。

    import itertools as it
    
    data = [
        {'N.': 'Sam', 'Batch': 2019, 'Sem': 'I', 'Sub': 'CAD', 'Files': 21, 'Type': 'dwg', 'Size(MB)': 98, 'uid': 732854},
        {'N.': 'Sam', 'Batch': 2019, 'Sem': 'I', 'Sub': 'CAD', 'Files': 8, 'Type': 'pdf', 'Size(MB)': 42, 'uid': 735554},
        {'N.': 'Sam', 'Batch': 2019, 'Sem': 'I', 'Sub': 'CAD', 'Files': 16, 'Type': 'docx', 'Size(MB)': 104, 'uid': 746748},
        {'N.': 'Sam', 'Batch': 2019, 'Sem': 'I', 'Sub': 'CAD', 'Files': 8, 'Type': 'pptx', 'Size(MB)': 57, 'uid': 731024},
        {'N.': 'Sam', 'Batch': 2019, 'Sem': 'I', 'Sub': 'CAM', 'Files': 8, 'Type': 'dwg', 'Size(MB)': 71, 'uid': 737328},
        {'N.': 'Sam', 'Batch': 2019, 'Sem': 'I', 'Sub': 'CAM', 'Files': 8, 'Type': 'docx', 'Size(MB)': 22, 'uid': 376494},
        {'N.': 'Sam', 'Batch': 2019, 'Sem': 'I', 'Sub': 'MIM', 'Files': 8, 'Type': 'pptx', 'Size(MB)': 28, 'uid': 687281},
        {'N.': 'Sam', 'Batch': 2019, 'Sem': 'I', 'Sub': 'MIM', 'Files': 8, 'Type': 'docx', 'Size(MB)': 20, 'uid': 687231},
        {'N.': 'Sam', 'Batch': 2019, 'Sem': 'I', 'Sub': 'MET', 'Files': 20, 'Type': 'pptx', 'Size(MB)': 204, 'uid': 457281},
    ]
    
    preferred_types = ('dwg', 'pdf', 'bmp')
    
    result = []
    
    key = lambda v:(v['N.'], v['Batch'], v['Sem'], v['Sub'])
    
    for _, values in it.groupby(data, key=key):
        values = sorted(values, key=lambda v:v['Type'] not in preferred_types)
        
        result.append(values[0])
        
        result.extend(value for value in values[1:] if value['Type'] in preferred_types)
                
    for row in result:
        print(row)
    

    【讨论】:

    • 我猜你一开始就错过了重点:1 个 API 调用返回 1 个字典。然而,连续的 API 调用一个接一个地返回集合 ['N.','Batch','Sem','Sub'] 的所有可能排列。要补充的是,任何固定集最多有 5-6 个变体。
    • 在我的示例中,前 4 个 dict(s) 连续返回,但所有 4 个都有单独的 API 调用。
    • @gagrot,在示例中,data 是所有行的列表。我的代码依赖于将相同 ['N.','Batch','Sem','Sub'] 组合在一起的“行”,data 可能是从 API 生成行的生成器。您没有提供有关 API 的任何信息,所以我只是使用了一个列表。
    • 我认为你搞错了兄弟。不存在初始数据列表。所有 API 都在旅途中被调用,并且单个 dict 正在旅途中被填充。所以我所有 1 个 API,它返回 1 个字典,然后我们使用我们的代码将它附加到最终列表中。然后第二个 API,第二个字典,使用代码,再次附加。抱歉,不清楚
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多