【问题标题】:Loop over multiple generators of multiple values循环多个值的多个生成器
【发布时间】:2018-10-19 19:27:21
【问题描述】:

我正在尝试检查两个给定字典的所有元素以确保它们相等,如果不是,我想要它们不同的属性名称。

这是我的基本方法:

# Dictionnaries
v1 = { "a" : { "b" : 1, "c" : 2 }, "d" : { "e" : { "f" : 3 }}}
v2 = { "a" : { "b" : 1, "c" : 2 }, "d" : { "e" : { "f" : 4 }}}

def gen(k, v):
    if type(v) is dict:
        for k in v:
            yield from gen(k, v[k])
    else:
        yield k, v

# Used alone the generator works as expected:
for k, v in gen("root", v1):
    print("{}: {}".format(k, v))

我的问题是我想比较这两个词典,据我所知,它应该是这样的:

for k1, v1, k2, v2 in zip(gen("root1", v1), gen("root2", v2)):
    print("{}: {}".format(k1, v1))
    print("{}: {}".format(k2, v2))
    print("===========")

解释器说只返回两个值,所以我认为这会起作用(确实如此):

for t1, t2 in zip(gen("root1", v1), gen("root2", v2)):
    print("{}: {}".format(t1[0], t1[1]))
    print("{}: {}".format(t2[0], t2[1]))
    print("===========")

我的问题:

这可能是纯粹的优惠,但我真的很想知道

  1. 我怎样才能让第一个循环工作,这样我就不必一直使用括号?
  2. 我尝试使用* 解压,但没有成功。为什么我不能zip(*gen(...), *gen(...))

(顺便说一句,我知道我可以在循环的开头添加k1, v1, k2, v2 = *t1, *t2,我只是在寻找更好的解决方案)

【问题讨论】:

    标签: python python-3.x loops dictionary generator


    【解决方案1】:

    您可以按如下方式解包每个返回的元组:

    for (k1, val1), (k2, val2) in zip(gen('root1', v1), gen('root2', v2)):
        ...
    

    【讨论】:

      【解决方案2】:

      您的问题更具体到语法,但您可能需要考虑一些事项:

      1. 字典是无序的集合,因此即使这些字典是相同的,只是因为它们以不同的顺序迭代,比较也可能会失败。
      2. Python 没有Tail Call Optimization,因此对于足够嵌套的字典,该代码将因堆栈溢出而失败。

      如果您想直观地比较字典,这里有一个解决这些问题的解决方案。

      假设:字典的结构是相同的(键是相同的,如果 1 的值是字典,它将是另一个字典,这些键不能是其他类型的迭代,例如列表)。

      from collections import deque
      
      def gen(dct1, dct2):
          q = deque()
          q.append(("root", dct1, dct2))
          while q:
              k, d1, d2 = q.pop()
              for key in d1:  # assuming the same keys for both dicts
                  val1 = d1[key]
                  val2 = d2[key]
      
                  # assuming that if the structure is the same -> if val1 is a dict, val2 is a dict as well 
                  if isinstance(val1, dict): 
                      q.append((k, val1, val2)) 
                  else:
                      yield key, val1, val2
      
      for k, val1, val2 in gen(v1, v2):
          print("{}: {}".format(k, val1))
          print("{}: {}".format(k, val2))
          print("===========")
      

      【讨论】:

      • 结构不保证相同,同样来自这个问题stackoverflow.com/questions/835092/…我认为你所说的并不完全正确,这是说而不是for k in v我可以简单地做for k in sorted(v)
      猜你喜欢
      • 2019-07-07
      • 2011-10-25
      • 2014-06-20
      • 2020-07-04
      • 1970-01-01
      • 2016-06-30
      • 2021-12-18
      • 2021-02-09
      • 1970-01-01
      相关资源
      最近更新 更多