在'for'循环中检测最后一个元素的Pythonic方式是什么?
我该怎么处理在用for
循环遍历时最后一个元素的特殊情况呢?特别是,如果有一些代码只想在元素之间执行,而不是在最后一个元素之后,我该怎么安排这些代码呢?
现在,我的代码是这样写的:
for i, data in enumerate(data_list):
code_that_is_done_for_every_element
if i != len(data_list) - 1:
code_that_is_done_between_elements
我该怎么简化或改进这个呢?
34 个回答
48
虽然这个问题已经有点时间了,但我通过谷歌找到了一个很简单的方法:列表切片。假设你想在列表的每个条目之间放一个'&'符号。
s = ""
l = [1, 2, 3]
for i in l[:-1]:
s = s + str(i) + ' & '
s = s + str(l[-1])
这样就会返回'1 & 2 & 3'。
51
如果这些项目是独一无二的:
for x in list:
#code
if x == list[-1]:
#code
还有其他选择:
pos = -1
for x in list:
pos += 1
#code
if pos == len(list) - 1:
#code
for x in list:
#code
#code - e.g. print x
if len(list) > 0:
for x in list[:-1]:
#process everything except the last element
for x in list[-1:]:
#process only last element
234
大多数情况下,把第一次的情况当作特殊情况处理,比把最后一次当作特殊情况要简单(而且便宜)得多:
first = True
for data in data_list:
if first:
first = False
else:
between_items()
item()
这个方法适用于任何可迭代的对象,甚至那些没有 len()
的对象:
file = open('/path/to/file')
for line in file:
process_line(line)
# No way of telling if this is the last line!
除此之外,我觉得没有一种通用的更好解决方案,因为这取决于你想要做什么。例如,如果你是想从一个列表中构建一个字符串,使用 str.join()
自然比用带有“特殊情况”的 for
循环要好。
使用同样的原则,但更简洁:
for i, line in enumerate(data_list):
if i > 0:
between_items()
item()
看起来很熟悉,对吧? :)
对于 @ofko 和其他需要确定没有 len()
的可迭代对象的当前值是否是最后一个的人,你需要往前看:
def lookahead(iterable):
"""Pass through all values from the given iterable, augmented by the
information if there are more values to come after the current one
(True), or if it is the last value (False).
"""
# Get an iterator and pull the first value.
it = iter(iterable)
last = next(it)
# Run the iterator to exhaustion (starting from the second value).
for val in it:
# Report the *previous* value (more to come).
yield last, True
last = val
# Report the last value.
yield last, False
然后你可以这样使用它:
>>> for i, has_more in lookahead(range(3)):
... print(i, has_more)
0 True
1 True
2 False