在Python中使用字符串作为切片索引?(TypeError:切片索引必须是整数、None或具有__index__方法的对象)

3

我有一个已排序的数组:

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

我想做类似于这样的事情:
arr['B':'M'] # ['Belman', 'Erik']

如何创建一个类并实现它

__getitem__

__index__

在正确的方式下如何实现这一点?
我正在考虑使用类似于以下内容的东西:
def __getitem__(self, key):
    if isinstance(key, slice):
        return [self.list[i] for i in range(key.start, key.stop)]
    return self.list[key]

但我不知道如何索引字符串。我该如何创建一个。
__index__

如何在self.list上应用二分搜索并返回正确的索引?


1
我不确定为什么 arr['B':'M'] 会提供你提供的输出。也许你的意思是 arr['B':'N']?另外,如果有多个字符串以相同的字母开头,会发生什么? - DeepSpace
Python中的bisect库。 - Chris_Rands
1
问题没有明确定义。例如,您想能够使用超过一个字符长度的字符串,像这样:arr['Bel':'Ni']? - Błotosmętek
1
这是你想要的例子吗?使用整数或对象名称在Python中索引列表。它覆盖了__getitem__方法。 - DarrylG
@DarrylG 谢谢!这就是我在寻找的。 - user12546101
显示剩余5条评论
2个回答

4
我认为你可以采用以下简单的实现方式:
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'])

将输出
['Belman', 'Erik']

同样地,
print(arr['Alex':'Er'])

将输出

['Alexander', 'Belman']

请注意,我使用了key.start <= e < key.stop以符合Python中始-终([))的包含性:排除性。同时请注意,我只实现了字符串切片用例。您可以根据需要实现其他用例和错误处理。

很棒的解决方案。使用整数或对象名称在Python中索引列表展示了如何通过将其委托给列表的__getitem__来处理“现在使用整数切片将会失败”的问题。 - DarrylG

0

我也用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!'
'''

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接