当一个值发生变化时,用 Pythonic 方式跳出元组迭代

Pythonic way to break out of iteration over tuples when one value changes

我有一组数据:

H         W         V
5         1         9.8385465 
10        1         8.2087544 
15        1         7.8788187 
20        1         7.5751283 
5         2         5.1217867 
10        2         4.3865578 
15        2         4.4089918 
20        2         4.0254478 

这已经被读入元组列表,称之为数据。 我想创建第二个列表,其中包含 H 的值,直到第一次重复,即完成时 H = [5,10,15,20]。有两个边界条件可以工作,当前 H 小于前一个,或者当前 W 大于前一个。

我考虑过简单地使用 enumerate(data) 并检查以前的与当前的,但是有更多 "pythonic" 的方法吗?

只存储之前的值:

previous = None

for H, W, V in data:
    if previous and previous != W:
        break
    #
    # do something with the values
    #
    previous = W

或者您可以跟踪唯一的 H 值:

seen = set()

for H, W, V in data:
    if H in seen:
        break
    seen.add(H)
    #
    # do something with the values
    #

或者您可以使用 itertools.groupby() 对元组中的第二个值进行分组,并且只使用第一组:

from itertools import groupby
from operator import itemgetter

group = next(groupby(data, itemgetter(1)))[1]
for H, W, V in group:
    # do something with the values

我会使用 while 循环。像这样:

w_at_start = data[0][1]
index = 0
while data[index][1] == w_at_start:
    # your actions
    index += 1

您可以使用 itertools.takewhile:

data = [
    (5, 1, 9.8385465),
    (10, 1, 8.2087544),
    (15, 1, 7.8788187),
    (20, 1, 7.5751283),
    (5, 2, 5.1217867),
    (10, 2, 4.3865578),
    (15, 2, 4.4089918),
    (20, 2, 4.0254478),
]

from itertools import takewhile, izip

print [data[0][0]] +[
    y[0] for x, y in takewhile(
        lambda _: _[0][0] <= _[1][0] and _[0][1] >= _[1][1],
        izip(data, data[1:])
    )
]

结果:

[5, 10, 15, 20]

编辑

更具可读性的版本:

from itertools import takewhile, izip, tee

data = ...


def criterion(_):
    prev, curr = _
    return prev[0] <= curr[0] and prev[1] >= curr[1]

it1, it2 = tee(iter(data))
print [next(it2)[0]] + [y[0] for x, y in takewhile(criterion, izip(it1, it2))]