简体   繁体   中英

Use strings as slice indices in Python ? (TypeError: slice indices must be integers or None or have an __index__ method)

I have a sorted array:

arr = ['Alexander', 'Belman', 'Erik', 'Nicholas', ... , 'Zahir']

I would like to do something like this:

arr['B':'M'] # ['Belman', 'Erik']

How can I create a class and implement

__getitem__
__index__

in the right way to achieve this ?

I am thinking of using something like

def __getitem__(self, key):
    if isinstance(key, slice):
        return [self.list[i] for i in range(key.start, key.stop)]
    return self.list[key]

but I don't know how to index the strings. How can I create an

__index__

method to apply a binarySearch to self.list and return the correct indices ?

I think you can get away with as simple implementation as below:

from collections import UserList

class MyList(UserList):
    def __getitem__(self, key):
        if isinstance(key, slice):
            return [e for e in self.data if key.start <= e < key.stop]
        # TODO implement the rest of the usecases and/or error handling...
        #      for now slicing with integers will miserably fail,
        #      and basic integer indexing returns None

arr = MyList(['Alexander', 'Belman', 'Erik', 'Nicholas', 'Zahir'])
print(arr['B':'M'])

which will output

['Belman', 'Erik']

likewise,

print(arr['Alex':'Er'])

will output

['Alexander', 'Belman']

Note that I used key.start <= e < key.stop to be in line with the inclusive:exclusive ( [) ) behavior which is used throughout python.

Also note that I implemented only the string slices usecase. You can implement the other usecases and error handling as you see fit.

I also post my solution with binary search using numpy

class Stock():

    def __init__(self, name, date):
        self.name = name
        self.date = np.array(date)


    def __getitem__(self, key):

        if isinstance(key, slice):
            if key.start is not None and key.stop is not None: 
                return self.date[np.searchsorted(self.date, key.start, side='left', sorter=None):np.searchsorted(self.date, key.stop, side='left', sorter=None)]
            elif key.start is not None:
                return self.date[np.searchsorted(self.date, key.start, side='left', sorter=None):]
            elif key.stop is not None:
                return self.date[:np.searchsorted(self.date, key.stop, side='left', sorter=None)]
            else:
                return self.date[:]

        i = np.searchsorted(self.date, key, side='left', sorter=None)
        if key != self.date[i]:
            raise KeyError('key: {} was not found!'.format(key))
        else:
            return self.date[i]



aapl = Stock('aapl', ['2010','2012', '2014', '2016', '2018'])

print(aapl['2011':])
print(aapl['2014':'2017'])
print(aapl[:'2016'])
print(aapl['2010'])
print(aapl['2013'])

'''
['2012' '2014' '2016' '2018']
['2014' '2016']
['2010' '2012' '2014']
2010
Traceback (most recent call last):
  File "C:\Users\...\Desktop\...\stock.py", line ##, in <module>
    print(aapl['2013'])
  File "C:\Users\...\Desktop\...\stock.py", line ##, in __getitem__
    raise KeyError('key: {} was not found!'.format(key))
KeyError: 'key: 2013 was not found!'
'''

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM