5

I am a beginner of python. I want to have arrays with arbitrary index running from p to q, instead of from 0.

How to create an array with q-p+1 elements with index from p to q?

4 Answers 4

7

You can create a subclass of list which adjusts the index on item-access:

class ListWithOffset(list):
    def __init__(self, offset, *a, **kw):
        self.offset = offset
        super().__init__(*a, **kw)

    def __getitem__(self, i):
        return super().__getitem__(self, self._adjust_idx(i))

    def __setitem__(self, i, value):
        return super().__setitem__(self, self._adjust_idx(i), value)

    def __delitem__(self, i):
        return super().__delitem__(self, self._adjust_idx(i))

    def _adjust_idx(self, i):
        if isinstance(i, slice):
            return slice(i.start - self.offset if i.start is not None else None,
                         i.stop - self.offset if i.stop is not None else None,
                         i.step)
        else:
            return i - self.offset

(edit: forgot to handle slicing)

Note it is not necessary to specify the end-index explicitly. It can change as the size of your list changes, and can be defined as mylist.offset + len(mylist) at any point in time.

Also note I kept the code snippet here in its simplest form, but for this to be useful you'd also need to handle the cases where the index passed is smaller than the offset. This implementation will likely return unexpected results (corresponding to list behavior when accessing negative indices), which is probably not ideal.

Sign up to request clarification or add additional context in comments.

Comments

4

There's no built-in syntax for what you're asking. It'll be easier if you just transform the desired range of indexes into the indexes of a standard list. For instance:

p = 10
q = 20
lst = [None for _ in range(q-p+1)] # initialize a list for the desired range

Now, to access any idx position in the range do this:

lst[idx-p]

For example:

lst[10-p] = 100
lst[10-p]
=> 100

lst[20-p] = 200
lst[20-p]
=> 200

Under the hood the list will look like this after the two assignments:

[100, None, None, None, None, None, None, None, None, None, 200]

Comments

4
  1. Use a dictionary:

    d = {}
    for i in range(5, 10):
        d[i] = f"something{i}"
    
  2. Or a dictionary comprehension:

    d = {i:f"something{i}" for i in range(5, 10)}
    
  3. Or an OrderedDict if insertion order matters and you're using Python 3.6 or lower:

    from collections import OrderedDict
    
    d = OrderedDict()
    for i in range(5, 10):
        d[i] = f"something{i}"
    

Usage

Elements can be retrieved with the same syntax as a list (Ideone Example):

print(d[7])

Output: something7

If you want to iterate the values of an OrderedDict use (Ideone Example):

for x in d.values():
    print(x)

Output:

something5
something6
something7
something8
something9

Comments

0

You can't do this with a list (and assuming you don't want to use a dictionary because you want the elements ordered) - however you can simulate it.

p = 10
q = 20
l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

#takes in index from 10 to 19 - throws exception otherwise
def get_elem(index):
    index = index-p
    if index > 0 and index < len(l):
        return l[index-p]
    else: 
        raise IndexError("list index out of range") 

print get_elem(13) #  prints 4

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.