Python 结构化一维序列

Python 结构化一维序列,有时需要通过某种形式将一维序列转换为复合序列,与前面的处理过程相比,可能更麻烦一些。可以用itertools模块的groupby()函数进行处理。

假设现有如下一个一维列表:

flat = ['2', '3', '5', '7', '11', '13', '17', '19', '23', '29',
 '31', '37', '41', '43', '47', '53', '59', '61', '67', '71',
 ... ]

使用嵌套生成器函数,可以把它从一维序列转换为复合序列。为了实现这一点,需要一个可多次使用的简单迭代器,表达式如下所示:

>>> flat_iter = iter(flat)
>>> (tuple(next(flat_iter) for i in range(5))
...     for row in range(len(flat)//5)
... )
<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'),
 ...
]

首先,在双层循环外部创建了一个用于生成复合序列的迭代器,生成器表达式使用tuple(next(flat_iter) for i in range(5)),基于变量flat_iter中的可迭代对象创建五元组。该表达式嵌于外层更大的生成器内,此生成器负责按照指定次数循环执行内层循环,生成最终的复合序列。

该表达式只适用于作为输入的一维列表能被子序列平分的情况,如果最后一行有剩余的元素,需要单独处理。

可以先使用上面的函数获得相同长度的元组,然后用下面的函数处理剩余长度不同的部分:

ItemType = TypeVar("ItemType")
Flat = Sequence[ItemType]
Grouped = List[Tuple[ItemType, ...]]

def group_by_seq(n: int, sequence: Flat) -> Grouped:
    flat_iter=iter(sequence)
    full_sized_items = list(tuple(next(flat_iter)
        for i in range(n))
            for row in range(len(sequence)//n))
    trailer = tuple(flat_iter)
    if trailer:
        return full_sized_items + [trailer]
    else:
        return full_sized_items

首先将长度为n的元组组成的列表提取到full_sized_items中,如果元素还有剩余,则将剩余元素组成一个元组,追加到full_sized_items后面。如果元组长度为0,则忽略trailer元组,返回原来的列表。

类型标示中包含了一个类型变量的抽象定义ItemType,用于表示函数的输入类型和输出类型是一致的,字符串序列或者浮点序列皆可。

函数的输入是由数据项组成的序列,输出是一个列表,元素为相同类型的数据项组成的元组。这里的数据项用ItemType表示,可以是任何类型。
这个实现不如之前的算法简洁,函数式特征也太不明显。可以把它改写成一个简单的生成器函数,生成可迭代对象而不是列表。

下面的代码使用while循环实现算法逻辑,并结合了尾递归优化:

ItemType = TypeVar("ItemType")
Flat_Iter = Iterator[ItemType]
Grouped_Iter = Iterator[Tuple[ItemType, ...]]

def group_by_iter(n: int, iterable: Flat_Iter) -> Grouped_Iter:
    row = tuple(next(iterable) for i in range(n))
    while row:
        yield row
        row = tuple(next(iterable) for i in range(n))

该函数从输入可迭代对象中抽取指定长度的行,当迭代至输入数据尾部时,tuple(next (iterable) for i in range(n))将会返回一个空元组,这是递归的基础型式,也是while循环的结束判断条件。

类型标示相应地修改成了包含迭代器的类型,不限于处理序列类型。由于显式使用了next()函数,需要这样使用:group_by_iter(7, iter(flat))。必须使用iter()函数将集合转换为迭代器。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程