Круговой диапазон индексов в Python

Я пытаюсь обработать партии вектора

скажем, у меня есть этот вектор

v = [10, 20, 30, 40, 70, 80, 90]

Я хочу напечатать каждые три элемента, если он доходит до конца, он возвращается к началу и берет первый элемент и так далее. Например, вывод будет примерно таким

10, 20, 30

40, 70, 80

90, 10, 20 <== начинается сначала

30, 40, 70

80, 90, 10 <== начинается сначала

и так далее...

Я знаю, что могу сделать это, создав функцию и вычислив начальный и конечный индекс с помощью модуля, но я подумал, есть ли способ просто поиграть с синтаксисом, что-то вроде

v[8:10 % 9]  #would print v[8], v[0] and v[1]

Я знаю, что вы можете сделать это для одного индекса v[index % len(v)], но возможно ли это сделать для диапазона v[range % len(v)]?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
0
395
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Хотя вычисление индексов возможно, я бы использовал itertools.cycle с группировщиком zip(*[] * x):

from itertools import cycle

v = [10, 20, 30, 40, 70, 80, 90]

n = 10

for index, *group in zip(range(n), *[cycle(v)] * 3):
    print(group)

Измените n на то, сколько раз вы хотите зациклить. Вывод:

[10, 20, 30]
[40, 70, 80]
[90, 10, 20]
[30, 40, 70]
[80, 90, 10]
[20, 30, 40]
[70, 80, 90]
[10, 20, 30]
[40, 70, 80]
[90, 10, 20]

У itertools есть ряд инструментов, которые могут вам в этом помочь:

from itertools import cycle, islice


def chunks(iterable, size):
    it = iter(iterable)
    item = list(islice(it, size))
    while item:
        yield item
        item = list(islice(it, size))


v = [10, 20, 30, 40, 70, 80, 90]


for subset in chunks(cycle(v), 3):
  print(subset)

который производит (выдает):

[10, 20, 30]
[40, 70, 80]
[90, 10, 20]
...

Функция chunks взята из здесь.

Если я правильно понимаю вашу проблему, вам нужна циклическая индексация. Я думаю, что есть два пути достижения этого. Как вы упомянули, с помощью явных функций и других ответов были разработаны. Но вы хотите добиться того же с помощью обычного синтаксиса списка (включая нарезку). Это возможно только в том случае, если вы сделаете подкласс из класса базового списка. Ниже приведен пример того, как это сделать:

class circularlist(list):
    def map_key(self, key):
        length = len(self)
        return key%length

    def __getitem__(self, key):
        if isinstance(key, int):
            return super().__getitem__(self.map_key(key))
        elif isinstance(key, slice):
            step = key.step if key.step else 1
            idx = [i for i in \
                   range(key.start, key.stop, step)]
            return [self.__getitem__(i) for i in idx]
        else:
            print(type(key))
            return super().__getitem__(key)

v = [10, 20, 30, 40, 70, 80, 90]
vv = circularlist(v)

print(vv[42])
print(vv[20:30])

Примечание. Я не рекомендую этого и предлагаю другие методы, описанные выше.

Другие вопросы по теме