Skip to content Skip to sidebar Skip to footer

Python/sage: Can Lists Start At Index 1?

I've downloaded from a supposedly serious source a sage script. It doesn't work on my computer, and a quick debugging showed that a problem came from the fact that at some point, t

Solution 1:

Python (and therefore sage) lists are always numbered from 0, and there isn't a way to change that.

Looking at CPython's source, in http://hg.python.org/cpython/file/70274d53c1dd/Objects/listobject.c on line 449:

static PyObject *
list_item(PyListObject *a, Py_ssize_t i)
{
    if (i < 0 || i >= Py_SIZE(a)) {
        if (indexerr == NULL) {
            indexerr = PyString_FromString(
                "list index out of range");
            if (indexerr == NULL)
                returnNULL;
        }
        PyErr_SetObject(PyExc_IndexError, indexerr);
        returnNULL;
    }
    Py_INCREF(a->ob_item[i]);
    return a->ob_item[i];
}

The item lookup delegates straight to the underlying C array, and C arrays are always zero-based. So Python lists are always zero-based as well.

Solution 2:

A simple class that shifts the index for you provides a clean interface to something reusable.

classArray(object):def__init__(self, items: list) -> None:self.items = items

    def__repr__(self) -> str:return'{}({})'.format(self.__class__.__name__, self.items)

    def__len__(self) -> int:return len(self.items)

    def__contains__(self, item: any) -> bool:return item inself.items

    def__getitem__(self, key: int) -> any:returnself.items[key - 1]

    def__setitem__(self, key: int, value: any) -> None:self.items[key - 1] = value

    def__delitem__(self, key: int) -> None:
        del self.items[key - 1]

Solution 3:

Well I too was facing the same idea on how to implement the method of indexing to be start from 1. I wanted to implement the Insertion Sort Algorithm which is as follows: Insertion Sort Algorithm

As we already know python list start from 0, what I did was following:

A = ['dummy',5,2,6,4,1,3]
for j inrange(2,len(A)):
    key = A[j]
    i=j-1while i>0and A[i]>key:
        A[i+1] = A[i]
        i = i-1
    A[i+1] = key
A.pop(0)
print A

I Just added a 'Dummy' in index 0, did all the work like in Algorithm and removed the 'dummy' again. This was just a cheating method.

Solution 4:

I would suggest subclassing e.g. collections.abc.MutableSequence for something like this, because once the protocol (in this case: __getitem__, __setitem__, __delitem__, __len__, insert) is implemented all list methods should work on the custom sequence type.

The solution I came up with uses collections.abc.MutableSequence with a list wrapper (_lst) and a helper class component that doesn't know much about anything except that it is subscriptable, i.e. it implements __getitem__ which handles the index modification.

import collections.abc

class_IndexComponent:def__getitem__(self, index):
        if index == 0: raise IndexError("Index 0 is a lie.")
        if index > 0: return index -1else:return index
        
classOneList(collections.abc.MutableSequence):def__init__(self, init: list = None) -> None:self._index_comp = _IndexComponent()
        self._lst = []
        ifnot init is None:# and isinstance(init, list)?self._lst.extend(init)
    
    def__getitem__(self, index: int) -> any:returnself._lst[self._index_comp[index]]

    def__setitem__(self, index: int, val: any) -> None:self._lst[self._index_comp] = val

    def__delitem__(self, index: int) -> None:
        del self._lst[self._index_comp[index]]

    def__len__(self) -> int:return len(self._lst)

    definsert(self, index: int, val: any) -> None:self._lst.insert(self._index_comp[index], val)

    def__repr__(self) -> str:return f"{self._lst}"

Now for example pop works although it isn't explicitly implemented:

ol = OneList([1,2,3,4])
print(ol.pop(1))
ol.pop(0) # IndexError

Somehow this feels kind of messy though, I would appriciate if someone shared a better solution.

l = [] l.extend([]) print(l)

Solution 5:

In [1]: index_0 = ['foo', 'bar', 'quux']

In [2]: index_1 = [None] + index_0

In [3]: index_1[1]
Out[3]: 'foo'In [4]: index_1[1:]
Out[4]: ['foo', 'bar', 'quux']

Post a Comment for "Python/sage: Can Lists Start At Index 1?"