【问题标题】:What's wrong with this nested list comprehension?这个嵌套列表理解有什么问题?
【发布时间】:2011-11-28 05:15:06
【问题描述】:
>>> c = 'A/B,C/D,E/F'
>>> [a for b in c.split(',') for (a,_) in b.split('/')]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <listcomp>
ValueError: need more than 1 value to unpack

预期结果是['A', 'C', 'E']

这就是我期望的方式,但显然它在 Python 中又回到了前面:

>>> [a for (a, _) in b.split('/') for b in c.split(',')]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'b' is not defined

【问题讨论】:

    标签: python python-3.x list-comprehension


    【解决方案1】:

    您失败的原因是 b.split('/') 没有产生 2 元组。 双重列表理解意味着您希望将笛卡尔积视为扁平流而不是矩阵。即:

    >>> [x+'/'+y for y in 'ab' for x in '012']
    ['0/a', '1/a', '2/a', '0/b', '1/b', '2/b']
        # desire output 0,1,2
        # not output 0,1,2,0,1,2
    

    您不是在寻找 6 个答案,而是在寻找 3 个。您想要的是:

    >>> [frac.split('/')[0] for frac in c.split(',')]
    ['A', 'C', 'E']
    

    即使您使用嵌套列表推导式,您也会得到笛卡尔积 (3x2=6) 并意识到您有重复的信息(您不需要 x2):

    >>> [[x+'/'+y for y in 'ab'] for x in '012']
    [['0/a', '0/b'], ['1/a', '1/b'], ['2/a', '2/b']]
        # desire output 0,1,2
        # not [0,0],[1,1],[2,2]
    

    以下是等效的做事方式。在这个比较中,我有点掩饰了生成器和列表之间的主要区别。

    列表形式的笛卡尔积:

    ((a,b,c) for a in A for b in B for c in C)
                #SAME AS#
    ((a,b,c) for (a,b,c) in itertools.product(A,B,C))
                #SAME AS#
    for a in A:
        for b in B:
            for c in C:
                yield (a,b,c)
    

    矩阵形式的笛卡尔积:

    [[[(a,b,c) for a in A] for b in B] for c in C]
                #SAME AS#
    def fC(c):
        def fB(b,c):
            def fA(a,b,c):
                return (a,b,c)   
            yield [f(a,b,c) for a in A]
        yield [fB(b,c) for b in B]
    [fC(c) for c in C]
                #SAME AS#
    Cs = []
    for c in C:
        Bs = []
        for b in B:
            As = []
            for a in A:
                As += [a]
            Bs += [As]
        Cs += [Bs]
    return Cs
    

    函数重复应用到列表

    ({'z':z} for x in ({'y':y} for y in ({'x':x} for x in 'abc')))
                  #SAME AS#
    for x in 'abc':
        x2 = {'x':x}
        y2 = {'y':x2}
        z2 = {'z':y2}
        yield z2
                  #SAME AS#
    def f(x):
        return {'z':{'y':{'x':x}}}
    return [f(x) for x in 'abc']     # or map(f,'abc')
    

    【讨论】:

      【解决方案2】:
      [x.split('/')[0] for x in [a for a in c.split(',')]]
      

      这会从 c = 'A/B,C/D,E/F' 获得所需的 ['A', 'C', 'E']

      【讨论】:

      • 为了以后参考,可以将(...)放在内部生成器周围,以避免创建不必要的中间列表,而不是[...]
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-06
      • 2013-05-10
      • 1970-01-01
      • 2011-12-24
      相关资源
      最近更新 更多