Skip to main content
 首页 » 编程设计

python之在 Python 中检查数据时避免嵌套循环

2025年05月04日13xxx_UU

我有两个字典列表:

dict_list1 = [{'k1':1, 'k2':2}, {'k1':3, 'k2':4}] 
dict_list2 = [{'k1':1, 'k2':2, 'k3':10}, {'k1':3, 'k2':4, 'k3':10}] 

现在对于 dict_list1 中的每个 dict_x,我想知道 dict_list2 上是否有一个 dict_y 包含来自 dict_x 的每个键和值。

除此之外我想不出另一种方法:

for dict_x in dict_list1: 
    for dict_y in dict_list2: 
        count = len(dict_x) 
        for key, val in dict_x.items(): 
            if key in dict_y and dict_y[key] == val: 
                count -= 1 
        if count == 0: 
            print('YAY') 
            break 

请您参考如下方法:

dict View 可以通过不等运算符执行快速“是子集”测试。所以:

if dict_x.items() <= dict_y.items():  # Use .viewitems() instead of .items() on Python 2.7 

仅当 dict_x 中的每个键/值对也出现在 dict_y 中时才会返回 true。

这不会改变 big-O 性能,但它确实使代码更简洁:

for dict_x in dict_list1: 
    for dict_y in dict_list2: 
        if dict_x.items() <= dict_y.items(): 
            print('YAY') 
            break 

请注意,创建 View 会花费一些(这只是固定成本,不依赖于 dict 大小),因此如果性能很重要,那么缓存 View 可能是值得的;为 dict_list1 这样做是免费的:

for dict_x in dict_list1: 
    dict_x_view = dict_x.items() 
    for dict_y in dict_list2: 
        if dict_x_view <= dict_y.items(): 
            print('YAY') 
            break 

但是需要一些急切的转换来缓存两者:

# Convert all of dict_list2 to views up front; costs a little if 
# not all views end up being tested (we always break before finishing) 
# but usually saves some work at the cost of a tiny amount of memory 
dict_list2_views = [x.items() for x in dict_list2] 
for dict_x in dict_list1: 
    dict_x_view = dict_x.items() 
    for dict_y_view in dict_list2_views: 
        if dict_x_view <= dict_y_view: 
            print('YAY') 
            break 

您还可以使用 any 来折叠循环(这消除了 break 的需要,因为 any 短路),所以第一个 (最简单的)检查可能变成:

for dict_x in dict_list1: 
    if any(dict_x.items() <= dict_y.items() for dict_y in dict_list2): 
       print('YAY') 

这可以进一步折叠为导致各种匹配的单个列表理解,但此时代码将变得非常局促/丑陋:

for _ in (dict_x in dict_list1 if any(dict_x.items() <= dict_y.items() for dict_y in dict_list2)): 
    print('YAY') 

虽然不知道您真正要做什么(而不是仅仅打印 YAY),但这变得有点毫无意义。