Python 平铺序列

Python 平铺序列,有时压缩后的数据需要平铺成一维序列,例如输入文件的结构可能如下所示:

2     3     5     7     11    13    17    19    23    29
31    37    41    43    47    53    59    61    67    71
...

可以用(line.split() for line in file)生成一个序列,序列的每个元素是文件中一行数据构成的十元组。

得到的数据结构如下所示:

>>> blocked = list(line.split() for line in file)
>>> blocked
[['2', '3', '5', '7', '11', '13', '17', '19', '23', '29'], ['31', '37',
'41', '43', '47', '53', '59', '61', '67', '71'], ['179', '181', '191',
'193', '197', '199', '211', '223', '227', '229']]

但这并不是我们想要的最终结果,我们希望得到的结构是一维序列,但实际输入的每个元素都是十元组。每次拆解一个这样的元组则太过麻烦。

平铺这类数据结构,可以使用如下所示的双层生成器表达式:

>>> (x for line in blocked for x in line)
<generator object <genexpr> at 0x101cead70>
>>> list(_)
['2', '3', '5', '7', '11', '13', '17', '19', '23', '29', '31',
 '37', '41', '43', '47', '53', '59', '61', '67', '71',
 ... ]

第一个for从句从blocked列表中解析出对象,每个对象是一个长度为10的列表,赋给line变量,第二个for从句从line变量中解析出字符串,赋给x变量,包含最终结果的生成器保存在x变量中。

改写成如下形式更易于理解:

def flatten(data: Iterable[Iterable[Any]]) -> Iterable[Any]:
    for line in data:
        for x in line:
            yield x

改写后可以看到生成器表达式的工作方式:外层for从句(for line in data)遍历输入数据中的每个十元组,内层for从句(for x in line)遍历外层语句中的每个元素。

这样双层序列复合型结构就转换成了单层序列。它能够将任何嵌套的双层可迭代对象转换为单层可迭代对象,例如双层列表、列表-集合组合结构等。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程