Python 用enumerate()添加序号,前面使用enumerate()
函数将等级值赋给排序后的数据。可以将一个值与它在原始序列中的位置序号组对,如下所示:
pairs = tuple(enumerate(sorted(raw_values)))
将raw_values
中的数据排序,生成一个升序排列的二元组序列,然后将它实例化,以备后续计算使用。表达式执行结果如下所示:
>>> raw_values = [1.2, .8, 1.2, 2.3, 11, 18]
>>> tuple(enumerate( sorted(raw_values)))
((0, 0.8), (1, 1.2), (2, 1.2), (3, 2.3), (4, 11), (5, 18))
前面实现的另一个版本的枚举函数rank()
处理数据的方式更符合统计计算的要求。
上面这种方法是解析原始数据文件来记录数据行号的常见做法。很多时候我们需要创建某种形式的row_iter()
函数从原始数据文件中提取字符串,例如遍历XML文件的标签或CSV文件列中的字符串,有时甚至需要通过Beautiful Soap库从HTML文件中解析数据。
前面通过解析XML文件生成简单的位置元组序列,然后生成了包含起点、终点和距离的路径段,但没有给路径段编号,因此当把路径段排序后,就无法获得路径段的原始顺序信息了。
前面拓展了基本解析器,创建了代表旅行路途中每个路径段的命名元组,这个增强版解析器的输出如下所示:
(Leg(start=Point(latitude=37.54901619777347, longitude=
-76.33029518659048), end=Point(latitude=37.840832, longitude=
-76.273834), distance=17.7246),
Leg(start=Point(latitude=37.840832, longitude=-76.273834),
end=Point(latitude=38.331501, longitude=-76.459503),
distance=30.7382),
Leg(start=Point(latitude=38.331501, longitude=-76.459503),
end=Point(latitude=38.845501, longitude=-76.537331),
distance=31.0756),
...,
Leg(start=Point(latitude=38.330166, longitude=-76.458504),
end=Point(latitude=38.976334, longitude=-76.473503),
distance=38.8019))
其中第一个Leg
对象表示Chesapeake Bay两地间的短途旅行。
下面创建一个能构造出更复杂元组的函数,将序号信息也加入元组中。首先定义一个更复杂的Leg
类:
from typing import NamedTuple
class Point(NamedTuple):
latitude: float
longitude: float
class Leg(NamedTuple):
start: Point
end: Point
distance: float
基本与前面中的Leg
定义相同,在保持原有属性的基础上增加了序号属性。下面定义函数拆解数据对并生成Leg
实例。
from typing import Iterator
def ordered_leg_iter(
pair_iter: Iterator[Tuple[Point, Point]]
) -> Iterator[Leg]:
for order, pair in enumerate(pair_iter):
start, end = pair
yield Leg(
order,
start,
end,
round(haversine(start, end), 4)
)
使用该函数枚举包含起点和终点的各对数据。拆解每个数据对,重新组合序号、起点、终点以及haversine(start, end)
参数,形成新的Leg
实例,该生成器函数的输入值是由数据对组成的可迭代序列。
根据前面的说明,该函数的用法如下所示:
filename = "file:./Winter%202012-2013.kml"
with urllib.request.urlopen(filename) as source:
path_iter = float_lat_lon(row_iter_kml(source))
pair_iter = legs(path_iter)
trip_iter = ordered_leg_iter( pair_iter )
trip = list(trip_iter)
首先将原始数据解析为路径点,然后基于Leg
对象生成旅行数据。这里用enumerate()
函数确保为每个元素分配一个从0开始依次递增且不会重复的序号。可以通过设置第二个参数来设置序号的起始值。