分割Python字符串的时间复杂度是多少?鉴于Python字符串是不可变的,我可以想象,根据切片的实现方式,对它们进行切片可以是O(1)
或O(n)
。
我需要编写一个函数来遍历(可能很大的)字符串的所有后缀。我可以通过将后缀表示为整个字符串的元组加上一个开始读取字符的索引来避免对字符串进行切片,但这很难看。如果我天真地这样写我的函数:
def do_something_on_all_suffixes(big_string):
for i in range(len(big_string)):
suffix = big_string[i:]
some_constant_time_operation(suffix)
。。。它的时间复杂度是O(n)
还是O(n2)
,其中n
是len(big_string)
?
简而言之:切片,通常是拷贝。这意味着为字符串的每个}s to get zero-copy views of the original bytes data 处理类似
n
后缀做切片的函数正在做O(n2)
工作。也就是说,如果可以使用^{bytes
的对象,就可以避免复制。有关如何使其工作,请参见下面的“如何执行零拷贝切片”。长答案:(C)Python
str
不要通过引用数据子集的视图来切片。对于str
切片,有三种操作模式:mystr[:]
:返回对完全相同str
的引用(不只是共享数据,相同的实际对象,mystr is mystr[:]
,因为str
是不可变的,所以这样做没有风险)mystr[1:1] is mystr[2:2] is ''
),长度1的低序数字符串也是单例缓存(在CPython 3.5.0上,看起来所有可以用拉丁文-1表示的字符,即range(256)
中的Unicode序数都被缓存)str
在创建时复制,之后与原始的str
无关之所以3是一般规则,是为了避免大的
str
被一小部分视图保存在内存中的问题。如果你有一个1GB的文件,读入它并像这样将其切片(是的,当你可以搜索时,这是浪费,这是为了说明):然后,您将有1GB的数据被保存在内存中,以支持显示最后1KB的视图,这是一种严重的浪费。由于切片通常很小,因此在切片上复制而不是创建视图几乎总是更快。它还意味着
str
可以更简单;它需要知道它的大小,但也不需要跟踪到数据中的偏移量。如何进行零拷贝切片
在Python中,有很多方法可以执行基于视图的切片,在Python 2中,它将在} that is a zero copy view of the original object ,并且可以在不复制数据的情况下进行切片。因此,如果您可以使用(或编码)Py2
str
上工作(因为str
与在python2中一样是字节,支持buffer protocol)。使用Py2str
和Py3bytes
(以及许多其他数据类型,如bytearray
、array.array
、numpy
数组、mmap.mmap
等),您可以创建一个^{str
/Py3bytes
,并且您的函数可以处理任意的bytes
类对象,那么您可以:memoryview
的切片确实生成了新的视图对象(它们只是超轻量级的,大小与它们所查看的数据量无关),只是没有任何数据,因此some_constant_time_operation
可以在需要时存储副本,并且在以后对其进行切片时不会更改。如果您需要一个正确的副本Py2str
/Py3bytes
,您可以调用.tobytes()
来获得原始的bytes
obj,或者(在Py3中只出现),直接将其解码到从缓冲区复制的str
,例如str(remaining_suffix[10:20], 'latin-1')
。这完全取决于你的切片有多大。我把以下两个基准组合在一起。第一个切片整个字符串,第二个只切片一点点。用this tool曲线拟合给出
第一个对于4MB以下的字符串片段看起来非常线性。我想这真的测量了构造第二个字符串所花费的时间。第二个是非常恒定的,虽然它太快了,可能不是那么稳定。
相关问题 更多 >
编程相关推荐