Выполните итерации по парам в списке (круговой вид) в Python

Бизнес-аналитика о понимании бизнеса. Это - нечетная обратная из Военной разведки, которая является о понимании врага. Это предоставляет искам информацию, с которой можно сделать бизнес-решения.

разработчику, это - тип программного обеспечения, которое можно было бы разработать. Не так тот, что разработчик использовал бы.

35
задан Colonel Panic 24 April 2017 в 14:38
поделиться

7 ответов

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

def ntuples(lst, n):
    return zip(*[lst[i:]+lst[:i] for i in range(n)])

Версия itertools должна быть достаточно эффективной даже для больших списков ...

from itertools import *
def ntuples(lst, n):
    return izip(*[chain(islice(lst,i,None), islice(lst,None,i)) for i in range(n)])

И версия для неиндексируемых последовательностей:

from itertools import *
def ntuples(seq, n):
    iseq = iter(seq)
    curr = head = tuple(islice(iseq, n))
    for x in chain(iseq, head):
        yield curr
        curr = curr[1:] + (x,)

В любом случае, спасибо всем за ваши предложения! : -)

9
ответ дан 27 November 2019 в 07:17
поделиться
def pairs(lst):
    i = iter(lst)
    first = prev = item = i.next()
    for item in i:
        yield prev, item
        prev = item
    yield item, first

Работает с любой непустой последовательностью, индексация не требуется.

27
ответ дан 27 November 2019 в 07:17
поделиться

Это бесконечное количество циклов, хорошее или плохое, но алгоритмически очень ясно.

from itertools import tee, cycle

def nextn(iterable,n=2):
    ''' generator that yields a tuple of the next n items in iterable.
    This generator cycles infinitely '''
    cycled = cycle(iterable)
    gens = tee(cycled,n)

    # advance the iterators, this is O(n^2)
    for (ii,g) in zip(xrange(n),gens):
        for jj in xrange(ii):
            gens[ii].next()

    while True:
        yield tuple([x.next() for x in gens])


def test():
    data = ((range(10),2),
        (range(5),3),
        (list("abcdef"),4),)
    for (iterable, n) in data:
        gen = nextn(iterable,n)
        for j in range(len(iterable)+n):
            print gen.next()            


test()

дает:

(0, 1)
(1, 2)
(2, 3)
(3, 4)
(4, 5)
(5, 6)
(6, 7)
(7, 8)
(8, 9)
(9, 0)
(0, 1)
(1, 2)
(0, 1, 2)
(1, 2, 3)
(2, 3, 4)
(3, 4, 0)
(4, 0, 1)
(0, 1, 2)
(1, 2, 3)
(2, 3, 4)
('a', 'b', 'c', 'd')
('b', 'c', 'd', 'e')
('c', 'd', 'e', 'f')
('d', 'e', 'f', 'a')
('e', 'f', 'a', 'b')
('f', 'a', 'b', 'c')
('a', 'b', 'c', 'd')
('b', 'c', 'd', 'e')
('c', 'd', 'e', 'f')
('d', 'e', 'f', 'a')
0
ответ дан 27 November 2019 в 07:17
поделиться

Я бы сделал это так (в основном потому, что я могу это прочитать):

class Pairs(object):
    def __init__(self, start):
        self.i = start
    def next(self):
        p, p1 = self.i, self.i + 1
        self.i = p1
        return p, p1
    def __iter__(self):
        return self

if __name__ == "__main__":
    x = Pairs(0)
    y = 1
    while y < 20:
        print x.next()
        y += 1

дает:

(0, 1)
(1, 2)
(2, 3)
(3, 4)
(4, 5)
(5, 6)
(6, 7)
(7, 8)
(8, 9)
2
ответ дан 27 November 2019 в 07:17
поделиться

Это может быть удовлетворительным:

def pairs(lst):
    for i in range(1, len(lst)):
        yield lst[i-1], lst[i]
    yield lst[-1], lst[0]

>>> a = list(range(5))
>>> for a1, a2 in pairs(a):
...     print a1, a2
...
0 1
1 2
2 3
3 4
4 0

Если вам нравятся подобные вещи, посмотрите статьи о Python на wordaligned.org . Особая любовь автора к генераторам на питоне.

5
ответ дан 27 November 2019 в 07:17
поделиться

Чтобы ответить на ваш вопрос о решении для общего случая:

import itertools

def pair(series, n):
    s = list(itertools.tee(series, n))
    try:
        [ s[i].next() for i in range(1, n) for j in range(i)]
    except StopIteration:
        pass
    while True:
        result = []
        try:
            for j, ss in enumerate(s):
                result.append(ss.next())
        except StopIteration:
            if j == 0:
                break
            else:
                s[j] = iter(series)
                for ss in s[j:]:
                    result.append(ss.next())
        yield result

Результат выглядит следующим образом:

>>> for a in pair(range(10), 2):
...     print a
...
[0, 1]
[1, 2]
[2, 3]
[3, 4]
[4, 5]
[5, 6]
[6, 7]
[7, 8]
[8, 9]
[9, 0]
>>> for a in pair(range(10), 3):
...     print a
...
[0, 1, 2]
[1, 2, 3]
[2, 3, 4]
[3, 4, 5]
[4, 5, 6]
[5, 6, 7]
[6, 7, 8]
[7, 8, 9]
[8, 9, 0]
[9, 0, 1]
0
ответ дан 27 November 2019 в 07:17
поделиться

Еще более короткая версия решения Fortran zip * range (на этот раз с лямбдой;):

group = lambda t, n: zip(*[t[i::n] for i in range(n)])

group([1, 2, 3, 3], 2)

дает:

[(1, 2), (3, 4)]
0
ответ дан 27 November 2019 в 07:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: