【问题标题】:Making list out of an iterator produces unexpected result从迭代器中创建列表会产生意想不到的结果
【发布时间】:2014-05-16 01:32:30
【问题描述】:

谁能解释一下为什么对从迭代器 X 生成的列表进行迭代与对迭代器 X 进行迭代相比会产生不同的结果?

换句话说 [x for x in list(IteratorObject)] != [x for x in IteratorObject]

>>> randoms = [random.randrange(10) for i in range(100)]

>>> [ (x[0],list(x[1])) for x in itertools.groupby(sorted(randoms))]
[(0, [0, 0, 0, 0, 0, 0, 0, 0]), (1, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]), (2, [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]), (3, [3, 3, 3, 3, 3, 3]), (4, [4, 4, 4, 4, 4, 4, 4, 4, 4, 4]), (5, [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5]), (6, [6, 6, 6, 6, 6, 6, 6, 6, 6]), (7, [7, 7, 7, 7, 7]), (8, [8, 8, 8, 8, 8, 8, 8]), (9, [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9])]

>>> [ (x[0],list(x[1])) for x in list(itertools.groupby(sorted(randoms)))]
[(0, []), (1, []), (2, []), (3, []), (4, []), (5, []), (6, []), (7, []), (8, []), (9, [9])]

>>> sys.version
'3.3.3 (default, Dec  2 2013, 01:40:21) \n[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.2.79)]'

【问题讨论】:

  • 你的预期输出是什么
  • 为了清楚起见,您能否将您的作业提供给randoms
  • 第一个结果是预期的。我添加了一个字符串来解释什么是随机数。

标签: python python-3.x iterator


【解决方案1】:

我认为文档中的这一点解释了问题:

"返回的组本身就是一个迭代器,它与 groupby() 共享底层迭代。因为源是共享的,所以当 groupby() 对象前进时,前一个组不再可见。所以,如果该数据是以后需要,应该存储为一个列表”

在您的第二个示例中,当您转换为列表时,您会立即遍历所有组。但是在每个组中,您不会遍历底层元素。当您最终尝试使用 list(x[1]) 执行此操作时,为时已晚 - 您已经用尽了迭代器。

【讨论】:

    【解决方案2】:

    itertools.groupby 为每个组生成的迭代器不独立于顶级迭代。在继续下一组之前,您需要消耗它们中的每一个,否则迭代器将变得无效(它不会产生任何进一步的结果)。

    the docs 中引用了此行为:

    返回的组本身就是一个迭代器,它与groupby() 共享底层迭代器。因为源是共享的,所以当groupby() 对象被推进时,之前的组不再可见。因此,如果以后需要该数据,则应将其存储为列表

    您的两个列表推导显示了这一点。在第一个中,您在 x[1] 上调用 list,这是迭代器。在第二个版本中,所有迭代器首先在 list 调用中围绕 groupby 调用生成,并且只有当您迭代该列表时,内部迭代器才会被消耗。请注意,最后一组 ([9]) 的迭代器确实有效!

    这是一个更简单的例子:

    groupby_iter = itertools.groupby([1,1,2,2])
    first_val, first_group = next(groupby_iter)
    
    # right now, we can iterate on `first_group`:
    print(next(first_group)) # prints 1
    
    # but if we advance groupby_iter to the next group...
    second_val, second_group = next(groupby_iter)
    
    # first_group is now invalid (it won't yield the second 1)
    print(next(first_group)) # raises StopIteration
    

    【讨论】:

      猜你喜欢
      • 2021-07-15
      • 1970-01-01
      • 2015-10-25
      • 2021-12-28
      • 1970-01-01
      • 2019-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多