从列表嵌套列表嵌套列表中取出第i个元素,并创建由这些第i个元素组成的列表,最优雅的编程方式(Pythonic)。

4

假设您有一个列表的列表,比如说

lll = [(['a', 'b'], [1, 2], [True, False]),
       (['c'], [3], [True]),
       (['d', 'e', 'f', 'g'], [4, 5, 6, 7], [True, False, True, False])]

对于lll中的每个项,我希望得到该项列表中第i个元素的列表,并将所有这些列表放在一个列表中。

正如你所想象的那样,用言语描述这个过程非常棘手,但是我希望最终结果像这样:

result = [
['a', 1, True],
['b', 2, False].
['c', 3, True],
['d', 4, True],
['e', 5, False],
['f', 6, True],
['g', 7, False]
]

我尝试过的是

newList = []
for item in lll:
    num_things = len(item[0])
    for ii in range(num_things):
        newList.append([x[ii] for x in item])

newList

有更符合 Python 风格的方式来得到这个结果吗?


你想要矩阵转置吗? - gilch
我曾经考虑过这个问题,但是它能够适用于长度不同的列表吗? - SantoshGupta7
如果您先将它们连接起来,那么可能会成功。 - gilch
4个回答

3

你的原始代码并不差。这些现有的答案都很好,但我认为

result = []

for item in lll:
    result.extend(zip(*item))

这样做相当简洁和符合Python风格,可以说比一行代码更易读,不需要导入任何内容,值得考虑。使用extend是将append与循环结合起来展开列表的常见重构方法,而zip几乎总是按列迭代和矩阵旋转的理想选择。

如果你需要列表而不是元组:

result = []

for item in lll:
    result.extend([list(x) for x in zip(*item)])

或者使用 map:
for item in lll:
    result.extend(map(list, zip(*item)))

以下是一些微小的风格建议,参考自PEP-8

  • 首选使用 snake_case 而不是 camelCase
  • 避免使用 l 作为变量名。因为它很容易被误认为是 i1

另外,num_things = len(item[0]) 看起来有点危险,因为如果 item 是空的话,它会引发 IndexError


3

使用没有导入任何模块的简单一行代码:

[[*ys] for xss in lll for ys in zip(*xss)]

zip-star操作调换元组中的位置,第二个for操作连接字符串,内部方括号将zip转化为列表。


@ggorlen,区别在于你的版本构建了一个元组列表,而我的版本构建了所请求的列表列表。类型不同。 - gilch
啊,好的。谢谢你澄清。你甚至在解释中写了那个 :-) - ggorlen

2
使用 zipchain.from_iterable
from itertools import chain

o = chain.from_iterable(zip(*ll) for ll in lll)
print(list(o))

# output
# [('a', 1, True), ('b', 2, False), ('c', 3, True), ('d', 4, True), ('e', 5, False), ('f', 6, True), ('g', 7, False)]

你可以使用列表推导式将每个元素映射到列表中,因为你想要的是列表而不是元组的列表。

l = [list(i) for i in o]
print(l)

# output
# [['a', 1, True], ['b', 2, False], ['c', 3, True], ['d', 4, True], ['e', 5, False], ['f', 6, True], ['g', 7, False]]


0

我相信你想要这个:

list(map(list,zip(*[sum(l,[]) for l in zip(*lll)])))

1
这是对 sum 函数的滥用,该函数仅适用于数字类型。在 CPython 中它目前可以作用于列表,但这只是实现细节,并不能保证在其他 Python 实现或未来版本中也能如此。请参阅 help(sum) - gilch
sum的文档字符串说:“此函数专门用于处理数字值,可能会拒绝非数字类型。” - gilch
但这是因为 "" 是不可变的,与 sum() 没有任何关系。你有 sum() 无法正常工作的示例吗? - Bobby Ocean
1
什么?不可变性与此无关。默认值 0 是相当不可变的,你知道的。 - gilch
我不知道你为什么对这个问题感到如此恐慌。sum()可以与其他东西一起使用,别纠结了。我同意它不起作用的原因可能不是因为不可变性,是我的错。但是,对于一个字符串来说,这显然是一个特殊的例外,甚至会弹出一个提醒使用''.join()函数。你有没有一个不是明确提醒另一个内置函数已经存在的例子?另外,0非常特殊,因为只有一个0;实际上,在内核中硬编码了从-5到256的每个数字都只有一个。 - Bobby Ocean
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接