Круговые пары из массива?

Я не могу поверить, что этого нигде не найти, но: я хочу, чтобы все последовательные пары из массива, включая последний элемент с первым. Я пробовал:

[(a, b) for a, b in zip(list, list[1:])]

Каков самый пифонический и эффективный способ сделать это?

Ответ 1

Другим подходом было бы использовать modulo для перехода от последнего элемента к первому:

l = [1,2,3,4,5,6]
n = len(l)
[(l[i], l[(i+1) % n]) for i in range(n)]

Он возвращает:

[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 1)]

Ответ 2

вам просто нужно добавить первый элемент во второй список:

l = [1,2,3,4,5,6]

r = [(a, b) for a, b in zip(l, l[1:]+l[:1])]

результат:

[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 1)]

Кроме того, "pythonic" также означает не использование list в качестве имени переменной.

Вариант: используйте itertools.ziplongest вместо zip и заполните первым элементом (в качестве бонуса, также работайте с массивами numpy, так как без добавления):

import itertools
r = [(a, b) for a, b in itertools.zip_longest(l, l[1:], fillvalue=l[0])]

Ответ 3

Здесь другой подход с использованием collections.deque:

>>> from collections import deque
>>> x = list(range(7))
>>> d = deque(x)
>>> d.rotate(-1)
>>> list(zip(x,d))
[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 0)]
>>>

Ответ 4

Я не оспариваю прохладу некоторых из этих ответов, но никто, кажется, не приурочил их, и с точки зрения "Pythonic" они могут получить немного неясное по сравнению с просто добавлением или расширением круговой части до конца,

l = xrange(1, 10000)

def simple_way(list_input):
    a = [(list_input[i], list_input[i+1]) for i in xrange(len(list_input)-1)]
    a.append((list_input[-1], list_input[0]))
    return a


timeit simple_way(l)
1000 loops, best of 3: 1.14 ms per loop

def top_rated_answer(list_input):
    n = len(list_input)
    a = [(list_input[i], list_input[(i+1) % n]) for i in xrange(n)]
    return a


timeit top_rated_answer(l)
1000 loops, best of 3: 1.37 ms per loop