用 Python 编程,使用不同的方法来完成同一个目标,有时候是一件很有意思的事情。这让我想起鲁迅笔下的孔乙己。孔乙己对于茴香豆的茴字的四种写法颇有研究。我不敢自比孔乙己,这里搜集一些 Python 的茴香豆,以飨各位码农。

假设有一个列表:source_list = [[1, 2, 3], [4, 5, 6], [7], [8, 9]] ,要求把这个列表拍扁,变成:[1, 2, 3, 4, 5, 6, 7, 8, 9]

这里我们先做一点准备工作:

import functools
import itertools
import numpy
import operator

source_list = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]

茴香豆一: for for

如果第一次面对这种问题,可能首先想到的就是 for ,基本的思路如下:

>>> flatten_list = []
>>> for sublist in source_list:
>>>    for item in sublist:
>>>        flatten_list.append(item)
>>> flatten_list
[1, 2, 3, 4, 5, 6, 7, 8, 9]

嗯,工作完成。

当然,如果你熟悉列表的推导的话,上面的一堆可以浓缩成:

[item for sublist in source_list for item in sublist]

茴香豆二: sum

python 有一个内置函数 sum ,这个函数本来是用来给我们做算术的,恰巧列表也是可以求和的,因此下面这句也能用:

sum(source_list, [])

numpy 也有类型的功能的 sum ,效果相同:

numpy.sum(numpy.array(source_list, dtype=object))

茴香豆三: numpy

numpy 还有专业拼接数组的工具,可以用来大炮打蚊子:

list(numpy.concatenate(source_list))

茴香豆四: numpy

多个东东变成一个东东,这不能不让我怀念起 reduce 的好:

functools.reduce(lambda x,y: x+y, source_list)
functools.reduce(operator.concat, source_list)
functools.reduce(operator.iconcat, source_list, [])

殊途同归,以上三条语句实现了同样的效果。

茴香豆五: chain

遇到列表的问题,高手们一般会亮出 chain ,以区别于一般俗手:

list(itertools.chain(*source_list))
list(itertools.chain.from_iterable(source_list))

茴香豆六: flatten

最后,请大家不要小看这个问题,但凡玩列表的,估计总有一天会遇到这个问题,不然前辈高人不会造这么多轮子的:

from pandas.core.common import flatten
list(flatten(source_list))

from matplotlib.cbook import flatten
list(flatten(source_list))

from setuptools.namespaces import flatten
list(flatten(source_list))