是否可以在Python3中使用类似缓冲区(基于指针)的字符串比较进行排序?
考虑对字符串的所有后缀进行排序的问题,其中后缀是从某个索引i到字符串末尾的子字符串。我们可以创建一个索引列表,对应于已排序后缀的起点,而不是创建已排序后缀的列表。然后我们可以这样做:是否可以在Python3中使用类似缓冲区(基于指针)的字符串比较进行排序?,python,python-3.x,Python,Python 3.x,考虑对字符串的所有后缀进行排序的问题,其中后缀是从某个索引i到字符串末尾的子字符串。我们可以创建一个索引列表,对应于已排序后缀的起点,而不是创建已排序后缀的列表。然后我们可以这样做: text = ... some text string ... sortedIndices = sorted([i for i in range(len(text))], key = lambda i: text[i:]) indexes = sorted(in
text = ... some text string ...
sortedIndices = sorted([i for i in range(len(text))],
key = lambda i: text[i:])
indexes = sorted(indexes, key = functools.cmp_to_key(lambda x,y:suffixArrayCompare(x, y)))
这适用于短字符串,但如果字符串足够长,我们将耗尽内存,因为key函数会生成后缀的副本,并且所有键都是从一开始生成的。在python 2.7中,有一种巧妙的解决方法,即buffer()函数:
sortedIndices = sorted([i for i in range(len(text))],
key = lambda i: buffer(text, i))
在本例中,键只是指向文本字符串的指针,因此所需的总内存要少得多(O(n)vs O(n*n))。因此,它将使用更长的字符串。这在2.7中运行得很好,但在3.x中,buffer()函数被删除,取而代之的是memoryview,它与buffer不同——AFAIK——不支持基于指针的字符串比较(即,不使用tobytes方法,该方法创建字符串的副本)。我的问题是:在Python3.x中有没有类似的方法 在我看来,memoryview并不能做到这一点。这实际上可能是件好事 您仍然可以使用更面向对象的类执行此操作:
#!/usr/local/cpython-3.3/bin/python
import sys
import functools
@functools.total_ordering
class Suffix_comparison:
def __init__(self, string, starting_position):
self.string = string
self.starting_position = starting_position
def __lt__(self, other):
if self.string[self.starting_position:] < other.string[other.starting_position]:
return True
else:
return False
def __eq__(self, other):
if self.string[self.starting_position:] == other.string[other.starting_position]:
return True
else:
return False
def __str__(self):
return self.string
__repr__ = __str__
def main():
list_ = []
for line in sys.stdin:
stripped_line = line.rstrip('\n')
list_.append(Suffix_comparison(stripped_line, 5))
list_.sort()
for line in list_:
print(line)
main()
#/usr/local/cpython-3.3/bin/python
导入系统
导入功能工具
@functools.total_排序
类后缀\u比较:
定义初始位置(自身、字符串、起始位置):
self.string=string
自启动位置=启动位置
定义(自身、其他):
如果self.string[self.starting_position:][other.string[other.starting_position]:
返回真值
其他:
返回错误
定义(自身、其他):
如果self.string[self.starting_position:][==other.string[other.starting_position]:
返回真值
其他:
返回错误
定义(自我):
返回self.string
__repr\uuuuu=\uuuuuu str__
def main():
列表\=[]
对于sys.stdin中的行:
stripped_line=line.rstrip('\n')
列表附加(后缀比较(剥离行,5))
list.sort()
对于列表中的行:
打印(行)
main()
我也一直在研究这个问题
我刚刚从Python2.7转换到了3。WinPython,它有一个非常酷的编辑器,顺便说一句,叫做Spyder
据我所知,memoryview对象是完全无用的
我还尝试了itertools.islice函数,但也看不出如何运行它
所以决定写我自己的小比较函数:
def后缀组合(x,y):
全球文本
i = 0
end = len(globalText) - max(x, y)
while i < end:
if globalText[x+i] < globalText[y+i]:
return -1
elif globalText[x+i] > globalText[y+i]:
return 1
i += 1
return 0
这是我跑得最快的速度了。它仍然没有2.7中的缓冲方式快,但也不太远。它不会复制任何东西
这个
运行速度几乎与您提到的一样快,但内存有问题。您似乎在解决与我提出的问题不同的问题。您正在对一组输入字符串中的固定长度后缀进行排序。我感兴趣的问题是对单个n字符输入字符串的所有后缀集(从长度1到长度n)进行排序。此外,您正在列表中存储所有类实例(每个实例都包含字符串),因此您将遇到相同的内存问题。仅考虑
后缀\u比较
,在lt\uuuuuu
和eq\uu
函数中存在错误。它可以通过与other.string[other.start\u position:][/code>进行比较来修复。
#indexes = sorted(indexes, key = lambda x: globalText[x:])