跳过可迭代对象的开始部分

问题

你想遍历一个可迭代对象,但是它开始的某些元素你并不感兴趣,想跳过它们。

解决方案

itertools 模 块 中 有 一 些 函 数 可 以 完 成 这 个 任 务。 首 先 介 绍 的 是
itertools.dropwhile() 函数。使用时,你给它传递一个函数对象和一个可迭代对
象。它会返回一个迭代器对象,丢弃原有序列中直到函数返回 True 之前的所有元素,
然后返回后面所有元素。

为了演示,假定你在读取一个开始部分是几行注释的源文件。比如:

>>> with open('/etc/passwd') as f:
... 	for line in f:
... 		print(line, end='')
...
##
# User Database
#
# Note that this file is consulted directly only when the system is running
# in single-user mode. At other times, this information is provided by
# Open Directory.
...
##
nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false
root:*:0:0:System Administrator:/var/root:/bin/sh
...
>>>

如果你想跳过开始部分的注释行的话,可以这样做:

>>> from itertools import dropwhile
>>> with open('/etc/passwd') as f:
... for line in dropwhile(lambda line: line.startswith('#'), f):
... print(line, end='')
...
nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false
root:*:0:0:System Administrator:/var/root:/bin/sh
...
>>>

这个例子是基于根据某个测试函数跳过开始的元素。如果你已经明确知道了要跳过的元素的个数的话,那么可以使用 itertools.islice() 来代替。比如:

>>> from itertools import islice
>>> items = ['a', 'b', 'c', 1, 4, 10, 15]
>>> for x in islice(items, 3, None):
... print(x)
...
1
4
10
15
>>>

在这个例子中, islice() 函数最后那个 None 参数指定了你要获取从第 3 个到最
后的所有元素,如果 None 和 3 的位置对调,意思就是仅仅获取前三个元素恰恰相反,
(这个跟切片的相反操作 [3:] 和 [:3] 原理是一样的)。

讨论

函数 dropwhile() 和 islice() 其实就是两个帮助函数,为的就是避免写出下面这种冗余代码:

with open('/etc/passwd') as f:
	# Skip over initial comments
	while True:
		line = next(f, '')
		if not line.startswith('#'):
			break
			
	# Process remaining lines
	while line:
		# Replace with useful processing
		print(line, end='')
		line = next(f, None)

跳过一个可迭代对象的开始部分跟通常的过滤是不同的。比如,上述代码的第一个
部分可能会这样重写:

with open('/etc/passwd') as f:
	lines = (line for line in f if not line.startswith('#'))
	for line in lines:
		print(line, end='')

这样写确实可以跳过开始部分的注释行,但是同样也会跳过文件中其他所有的注
释行。换句话讲,我们的解决方案是仅仅跳过开始部分满足测试条件的行,在那以后,
所有的元素不再进行测试和过滤了。

最后需要着重强调的一点是,本节的方案适用于所有可迭代对象,包括那些事先不
能确定大小的,比如生成器,文件及其类似的对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值