在Python 3中如何展开多维数组

8

我有一个数字列表:testList = [1,[1],[12],2,3]

我想让它变成:flatList = [1,1,12,2,3]

使用通常的列表推导式无法实现。

flatList = [val for sublist in testList for val in sublist]
TypeError: 'int' object is not iterable

我怀疑问题出现在未嵌套的项被视为可迭代子列表,因此我尝试了以下方法:

flatList = [val if isinstance(sublist, int) == False else val for sublist in testlist for val in sublist]

但我不清楚语法,或者是否有更好的方法来完成这个操作。试图从else子句中删除val意味着val未定义。目前这样做仍然会给我同样的TypeError。

以下代码对我有效,但我想知道它是否可以以列表推导式的方式完成,并听取人们对此的意见。

for sublist in testlist:
    if type(sublist) == int:
        flat.append(sublist)
    else:
        for val in sublist:
            flat.append(val)
print(flat)

>>>[1, 1, 12, 2, 3]

子列表可以包含多个整数吗? - AidanH
1
在 else 块中,您可以用 flat.extend(sublist) 替换 for 循环。 - Abhijith Asokan
它可以包含多个整数。 - CameronAtkinson
@stack_n_queue,感谢您指出这一点。 - CameronAtkinson
2个回答

6

由于您正在使用Python 3,您可以利用递归函数中引入的yield from。它在Python 3.3中被引入。

作为奖励,您可以展平任意嵌套的列表、元组、集合或范围:

test_list = [1, [1], [12, 'test', set([3, 4, 5])], 2, 3, ('hello', 'world'), [range(3)]]

def flatten(something):
    if isinstance(something, (list, tuple, set, range)):
        for sub in something:
            yield from flatten(sub)
    else:
        yield something


print(list(flatten(test_list)))
# [1, 1, 12, 'test', 3, 4, 5, 2, 3, 'hello', 'world', 0, 1, 2]
print(list(flatten('Not a list')))
# ['Not a list']
print(list(flatten(range(10))))
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

这是另一个带有调试行的示例:

def flatten(something, level=0):
    print("%sCalling flatten with %r" % ('  ' * level, something))
    if isinstance(something, (list, tuple, set, range)):
        for sub in something:
            yield from flatten(sub, level+1)
    else:
        yield something

list(flatten([1, [2, 3], 4]))
#Calling flatten with [1, [2, 3], 4]
#  Calling flatten with 1
#  Calling flatten with [2, 3]
#    Calling flatten with 2
#    Calling flatten with 3
#  Calling flatten with 4

我会将something命名为iterable - Daniel
好吧,由你决定,但如果“something”不是可迭代的(因为在整数和字符串上调用flatten没有意义),我会引发一个TypeError。 - Daniel
好的,我现在明白了。我经常对递归感到困惑 :) - Daniel
2
哇,非常有用。这不是我熟悉的函数,很高兴看到isinstance()如何与多种类型一起使用。 - CameronAtkinson

2
如果子列表始终只包含一个项目,则
flatList = [item[0] if isinstance(item, list) else item for item in testList]

谢谢,对于那些情况很有用。 - CameronAtkinson

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