Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can list[n] point to list[0]? Getting items not in sequence

Tags:

python

I'm not sure about the term of this technique. I want to create a list where if I try to access an element outside the list range, the list would "loop itself". Example of the behaviour I want to achieve:

>>> musical_scale = ['C', 'D', 'E', 'F', 'G', 'A', 'B']
>>> musical_scale[2]
E
>>> musical_scale[7]
C
>>> musical_scale[-1]
B

I guess I could write a class which does this, but I thought there might be a more correct way of doing it.

like image 341
Erik Sjöstrand Avatar asked Mar 18 '23 16:03

Erik Sjöstrand


1 Answers

Creating a subclass of List would be a pretty useful way of doing this. Something like this, perhaps:

class modList(list):

  def __getitem__(self, i):
    if len(self) == 0:
      raise IndexError   # Or do something else if you want, like return []
    i = i % len(self)   # self.__len__() works also
    return super(modList, self).__getitem__(i)   # In Python 3, super().__getitem__(i)

If you want to do slicing, it's a little more complicated, but similar. Found this while looking through StackOverflow:

  def __getitem__(self, i):
    if isinstance(i, int):
      if len(self) == 0:
        raise IndexError
      i = i % len(self)
      return super(modList, self).__getitem__(i)   # list.__getitem__(i) works too
    elif isinstance(i, slice):
      if len(self) == 0:
        return []
      start = i.start % len(self)
      stop = i.stop % len(self)
      step = i.step
      return super(modList, self).__getItem__(slice(start, stop, step))
    else:
      raise TypeError("invalid index")

Though this slice modding could give you a situation like [3:2], which will return an empty list. Basically slicing is hard and you'll need to decide how you want to implement it, but hopefully this is a start.

http://www.stackoverflow.com/questions/3911483/python-slice-how-to-i-know-the-python-slice-but-how-can-i-use-built-in-slice-ob

(Thanks @JonClements for all the suggestions in chat.)

EDIT: now we have some handlers for if you have an empty list. @wim suggests raising an error for single accesses, and returning [] for slices. Really it's up to you what you want to do but that seemed sensible to me, so that's what I've included in this answer.

EDIT EDIT: if you're using Python 2.x, I believe you also need to override __getslice__.

like image 159
TheSoundDefense Avatar answered Apr 28 '23 00:04

TheSoundDefense