问题
迭代一个序列的同时跟踪正在被处理的元素索引。
解决方案
内置的 enumerate()
函数可以很好的解决这个问题:
my_list = ['a', 'b', 'c']
for key, value in enumerate(my_list):
print(key, value)
0 a
1 b
2 c
为了按传统行号从1开始输出,你可以传递一个开始参数:
for key, value in enumerate(my_list, 1):
print(key, value)
1 a
2 b
3 c
enumerate()
函数对于跟踪某些值在列表中出现的位置是很有用的。比如,想将一个文件中出现的单词映射到它出现的行号上去:
word_summary = defaultdict(list)
with open('/Users/xz/test/Bath.txt', 'r+') as f:
lines = f.readlines()
for idx, value in enumerate(lines, 1):
words = [w.strip(",.").lower() for w in value.split()]
for word in words:
word_summary[word].append(idx)
print(word_summary)
defaultdict(<class 'list'>, {'i': [1, 1, 1, 1, 2, 3], 'will': [1], 'not': [1, 3], 'take': [1, 3], 'a': [1, 2, 2, 2, 2, 3], 'bath': [1, 1, 3], 'won’t': [1], 'get': [1], 'in': [1], 'tub': [1, 3], 'has': [1], 'last': [1], 'week': [1], 'don’t': [1], 'need': [1, 2], 'another': [1], 'scrub': [1], 'would': [2], 'my': [2, 2], 'rubber': [2, 2], 'duck': [2], 'bucket': [2], 'and': [2], 'boat': [2], 'toy': [2, 3], 'whale': [2], 'submarine': [2], 'ball': [2], 'now': [3], 'can': [3], 'the': [3], 'is': [3], 'too': [3], 'small': [3], 'it’s': [3], 'all': [3], 'filled': [3], 'up': [3], 'with': [3], 'there’s': [3], 'no': [3], 'room': [3], 'for': [3], 'me': [3]})
打印结果 word_summary ,它是一个defaultdict字典,每个单词有一个 key ,每个 key 对应的值是一个由这个单词出现的行号组成的列表。 如果某个单词在一行中出现过两次,那么这个行号也会出现两次, 同时也可以作为文本的一个简单统计。
讨论
当需要额外定义一个计数变量的时候,使用 enumerate()
函数会更加简单。比如:
lineno = 1
for line in f:
# Process line
...
lineno += 1
使用 enumerate() 函数来代替就显得更加优雅了:
for lineno, line in enumerate(f):
# Process line
...
enumerate()
函数返回的是一个 enumerate
对象实例, 它是一个迭代器,返回连续的包含一个计数和一个值的元组, 元组中的值通过在传入序列上调用 next()
函数返回。
需要注意的是,当在一个已经解压后的元组序列上使用 enumerate()
函数时很容易调入陷阱。示例:
data = [ (1, 2), (3, 4), (5, 6), (7, 8) ]
# Correct!
for n, (x, y) in enumerate(data):
...
# Error!
for n, x, y in enumerate(data):
...
网友评论