在Python中按对迭代列表的最简洁方法是什么?

时间:2019-04-03 08:47:34

标签: python-3.x

我有以下蛮力选项,可以让我遍历各个点:

# [x1, y1, x2, y2, ..., xn, yn]
coords = [1, 1, 2, 2, 3, 3]
# The goal is to operate with (x, y) within for loop
for (x, y) in zip(coords[::2], coords[1::2]):
   # do something with (x, y) as a point

是否有更简洁/有效的方法?

2 个答案:

答案 0 :(得分:2)

({def python_func(**kwargs): ts = kwargs["execution_date"] end_time = str(ts) start_time = str(ts.add(minutes=-30)) -> coords

简短回答

如果您希望将商品的长度指定为2,则

items
就速度和清晰度而言,

是最好的折衷之一。 如果您负担得起额外的一行,则可以通过使用迭代器来提高效率(对于较大的输入,很多):

zip(items[::2], items[1::2])

长答案

(编辑:添加了避免使用it = iter(items) zip(it, it) 的方法)

您可以通过多种方式实现这一目标。 为了方便起见,我将它们编写为可以进行基准测试的函数。 另外,我会将组的大小保留为参数zip()(在您的情况下为n

2

将这些标记为相对简短的列表即可:

def grouping1(items, n=2):
    return zip(*tuple(items[i::n] for i in range(n)))


def grouping2(items, n=2):
    return zip(*tuple(itertools.islice(items, i, None, n) for i in range(n)))


def grouping3(items, n=2):
    for j in range(len(items) // n):
        yield items[j:j + n]


def grouping4(items, n=2):
    return zip(*([iter(items)] * n))


def grouping5(items, n=2):
    it = iter(items) 
    while True: 
        result = [] 
        for _ in range(n): 
            try: 
                tmp = next(it) 
            except StopIteration: 
                break 
            else: 
                result.append(tmp) 
        if len(result) == n: 
            yield result 
        else: 
            break

对于中型输入:

short = list(range(10))

%timeit [x for x in grouping1(short)]
# 1.33 µs ± 9.82 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%timeit [x for x in grouping2(short)]
# 1.51 µs ± 16.8 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%timeit [x for x in grouping3(short)]
# 1.14 µs ± 28.8 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%timeit [x for x in grouping4(short)]
# 639 ns ± 7.56 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%timeit [x for x in grouping5(short)]
# 3.37 µs ± 16.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

对于较大的输入:

medium = list(range(1000))

%timeit [x for x in grouping1(medium)]
# 21.9 µs ± 466 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit [x for x in grouping2(medium)]
# 25.2 µs ± 257 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit [x for x in grouping3(medium)]
# 65.6 µs ± 233 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit [x for x in grouping4(medium)]
# 18.3 µs ± 114 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit [x for x in grouping5(medium)]
# 257 µs ± 2.88 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

就效率而言,large = list(range(1000000)) %timeit [x for x in grouping1(large)] # 49.7 ms ± 840 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) %timeit [x for x in grouping2(large)] # 37.5 ms ± 42.4 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) %timeit [x for x in grouping3(large)] # 84.4 ms ± 736 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) %timeit [x for x in grouping4(large)] # 31.6 ms ± 85.7 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) %timeit [x for x in grouping5(large)] # 274 ms ± 2.89 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) 似乎是最快的,紧随其后的是grouping4()grouping1()(取决于输入的大小)。

对于您来说,grouping3()似乎是速度和清晰度之间的良好折衷,除非您愿意将其包装在函数中。

请注意,grouping1()要求您多次使用同一迭代器,并且:

grouping4()

不起作用。

如果您想更好地控制不均匀分组,即在zip(iter(items), iter(items)) 无法将len(items)整除的情况下,可以从标准库中将n替换为zip

还要注意,itertools.zip_longest()基本上是itertools official documentation中的grouping4()配方。

答案 1 :(得分:-1)

您可以将iter(object)next(iterator, default)与已知的 default 一起使用来退出循环:

coords = [1, 1, 2, 2, 3, 3]
it = iter(coords)

while it:
    x = next(it, None)
    y = next(it, None)
    if x is None or y is None:
        break

    # do something with your pairs
    print(x,y) 

输出:

1 1
2 2
3 3