代码之家  ›  专栏  ›  技术社区  ›  Dilawar

'list(itertools.groupy)`[重复]的反直觉行为

  •  3
  • Dilawar  · 技术社区  · 6 年前

    让我来演示一下。它已经咬了我两次,第一次我放弃了思考,我不明白怎么会这样 groupby 作品我正在使用“Python3”。6’。

    我有一个元素列表 x.y 要分组的格式 y

    a = ['1D.5', '2D.5', '3D.5', '1D.10', '2D.10', '3D.10', '1D.20', '2D.20', '3D.20', '1D.100', '2D.100', '3D.100']
    groups = list(itertools.groupby(a, key=lambda x: x.split('.')[-1]))
    for gname, glist in groups:
        print(list(glist))
    

    这将导致以下结果。

    []
    []
    []
    ['3D.100']
    

    奇怪的

    然而,这是可行的。

    groups = itertools.groupby(a, key=lambda x: x.split('.')[-1])
    for gname, glist in groups:
        print(list(glist))
    
    ['1D.5', '2D.5', '3D.5']
    ['1D.10', '2D.10', '3D.10']
    ['1D.20', '2D.20', '3D.20']
    ['1D.100', '2D.100', '3D.100']
    

    不同的是这次我没有打电话 list itertools.groupby 。这种行为背后肯定有一些技术原因,但根据我对python生成器的经验,这是非常违反直觉的,可能是错误的!

    为什么要打电话 列表 在迭代器上是否使其内容无效?

    PS: 的文档 子句 在其实现细节中有以下两行。

    # [k for k, g in groupby('AAAABBBCCDAABBB')] --> A B C D A B
    # [list(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D
    

    我的怀疑对吗 list(some generator) 不保证给出与“等效”列表理解相同的结果吗?

    1 回复  |  直到 6 年前
        1
  •  2
  •   Dan D.    6 年前

    groupby 的组迭代器依赖于前面的迭代器。因此,从这些组迭代器中创建列表的正确方法是确保在生成每个迭代器时复制它们。

    list((g, list(it)) for g, it in itertools.groupby(a, key=func))
    

    外部 list 单独不会复制内部迭代器 it 只能按顺序访问一次。