我有以下蛮力选项,可以让我遍历各个点:
# [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
是否有更简洁/有效的方法?
答案 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