2

I am trying to process batches of a vector

let say, I have this vector

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

I want to print every three elements, if it reaches the end, it goes back to the beginning and takes the first to element and so on. For example, the output would be something like

10, 20, 30

40, 70, 80

90, 10, 20 <== starts over

30, 40, 70

80, 90, 10 <== starts over

and so on...

I know I can do this creating a function and calculating the start and end index using module, but I was thinking if there is a way just playing with the sintaxis, something like

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

I know you can do this for a single index v[index % len(v)], but is it possible to do it for a range v[range % len(v)] ?

zeellos
  • 139
  • 11

3 Answers3

1

Though computing indexes is possible, I would use itertools.cycle with the zip(*[] * x) grouper:

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)

Change n to however many times you want to loop. Output:

[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]
iz_
  • 15,923
  • 3
  • 25
  • 40
1

itertools have a number of tools that can help you with that:

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)

which produces (yields):

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

The chunks function has been taken from here

Ma0
  • 15,057
  • 4
  • 35
  • 65
0

If I understand your problem correctly, you want circular indexing. I think there are two ways of achieving this. Through explicit functions, as you mentioned, and other answers have elaborated. But you want to achieve the same through usual list syntax (including slicing). It is only possible if you make a subclass out of base list class. Below is an example of doing this:

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])

Note: I do not recommend this, and suggest the other methods above.

Prodipta Ghosh
  • 509
  • 4
  • 14