【问题标题】:iterate 2 dicts and compare values then append inner list迭代 2 个字典并比较值,然后附加内部列表
【发布时间】:2023-03-11 01:57:02
【问题描述】:

我面临这样一种情况,我需要使用相同的最外层键迭代嵌套的字典,将内键值与其他字典的内键值进行比较,然后追加。下面将有助于理解:

{AD:{(62,'VMX','Barcelona','ES'): ['123','567','666'}} #dict1  many more rows

{AD:{(151,'CMXS','','ES','62'): ['345','6754']}}       #dict 2 many more rows

所以我需要迭代两个 dicts,比较 dict1 的元组键 [0] == dict2 的元组键 [4],如果它们匹配 dict1 中的追加内部列表和 dict2 中的内部列表。

这个dict1之后的样子

{AD:{(62,'VMX','Barcelona','ES'): ['123','567','666','345','6754'}}

写了这段代码,但它没有按预期工作

for k,v in dict1.items():
    if len(v)!= 0:
        for c,a in dict2.items():
            if len(a)!= 0:
                for k2,v2 in v.items():
                    for c2,a2 in a.items():
                        if str(k2[0]) == c2[4]:
                            v2.append(a2)

【问题讨论】:

  • 深度只有两个层次对吧?
  • 是的,只有 2 层深,但这个嵌套循环的问题是,它还附加到 str(k2[0]) == c2[4]) 的所有其他情况。就像最外层的键与 AD 不同。
  • 如果您希望最外层的键相同,请添加and k == c 条件。即if (k == c) and (str(k2[0]) == c2[4])
  • 或者,跳过第二个 for 循环,只循环具有相同外键的字典。 a = dict2[k].
  • @algrebe 您好,您的第一条评论使它起作用。你能解释一下摆脱第二个for循环的意思吗?讨厌2个嵌套循环。很多不必要的比较

标签: python list dictionary for-loop compare


【解决方案1】:
dict1 = {"AD":{(62,'VMX','Barcelona','ES'): ['123','567','666']}} #dict1  many more rows

dict2 = {"AD":{(151,'CMXS','','ES','62'): ['345','6754']}}       #dict 2 many more rows

# create a simplified map of dict2
dict3 = {}
for outer_key, outer_value_dict in dict2.items():
    for inner_key_tuple, inner_value_list in outer_value_dict.items():
        new_key = (outer_key, inner_key_tuple[4]) # e.g. (AD, 62)
        dict3.setdefault(new_key, []).extend(inner_value_list)

# now modify dict1 using dict3 instead of dict2
for outer_key, outer_value in dict1.items():
    for inner_key_tuple, inner_value_list in outer_value.items():
        lookup_key = (outer_key, str(inner_key_tuple[0]))
        # search dict3 using the lookup_key.
        # if not present, get will return an empty list
        list_to_extend = dict3.get(lookup_key, [])
        inner_value_list.extend(list_to_extend)

print(dict1)

输出

/tmp $ python test.py.py
{'AD': {(62, 'VMX', 'Barcelona', 'ES'): ['123', '567', '666', '345', '6754']}}

基于 cmets,因为您想知道如何避免其中一个循环 - 这是一个更新版本

for k,v in dict1.items():
    a = dict2.get(k)
    if a is None or len(v) == 0:
        continue

    for k2,v2 in v.items():
        for c2,a2 in a.items():
            if str(k2[0]) == c2[4]:
                v2.append(a2)

【讨论】:

  • 这使它更干净。我认为有一种方法可以避免制作另一个字典。但这确实有效。谢谢。
  • 我也用我在 cmets 中的意思更新了它
  • 请对此发表评论。由于 next 没有被迭代,它不起作用for k,v in dict1.items(): if len(v)!= 0: for k2,v2 in v.items(): if str(k2[0]) == next(iter(dict2[k]))[4]: v2.append(dict2[k][next(iter(dict2[k]))])
  • @NaiveBayes 您能否详细说明您的评论?你在尝试新的东西吗?另一种方法?
  • @NaiveBayes next(iter(dict2[k]))。首先,这假设 k 是 dict2 的一部分。如果不是,您将收到 KeyError。这就是我使用.get(k) 并检查它是否为无的原因。此外,这将始终将 k2[0] 与 dict2[k] 中的单个键进行比较。您希望它与第 4 个元素匹配 k2[0] 的每个元组进行比较。所以你不能摆脱for c2,a2 in a.items() for 循环。
【解决方案2】:

只要示例进行,for 循环就会正确放置。

意外是什么意思? 你是这个意思吗?

{'AD': {(62, 'VMX', 'Barcelona', 'ES'): ['123', '567', '666', ['345', '6754']]}}

数组中的那个额外数组?

因为如果是这样,答案是用 .extend() 切换 .append()

【讨论】:

  • 嗨,有没有比使用 2 个嵌套循环更好的方法,考虑到这对于大字典效率不高,或者如果我需要比较 3 个字典?追加/扩展不是问题。问题在于附加的值。 @algrebe 的评论解决了这个问题。但还是想知道更好的方法
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-23
  • 2020-07-12
  • 2020-06-26
  • 1970-01-01
  • 2011-05-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多