有一个代码使用lambda表达式
def ComputeArray(text):
# text is ended with $
if text[-1] != "$":
text += "$"
sarray = sorted(range(len(text)), key = lambda i: text[i:])
print ", ".join([str(x) for x in sarray])
if __name__ == "__main__":
ComputeArray("AACGATAGCGGTAAACGATAGCGGTAGA$")
它正确输出所需的数组
28, 27, 12, 0, 13, 1, 14, 25, 6, 19, 4, 17, 2, 15, 8, 21, 26, 3, 16, 7, 20, 9, 22, 10, 23, 11, 24, 5, 18
我怎样才能提高行
sarray = sorted(range(len(text)), key = lambda i: text[i:])
所以当增加文本长度时,我不会在lambda表达式上使用大量内存吗?
Traceback (most recent call last):
File "C:\Array.py", line 23, in <module>
ComputeArray(text)
File "C:\Array.py", line 11, in ComputeArray
sarray = sorted(range(len(text)), key = lambda i: text[i:])
File "C:\Array.py", line 11, in <lambda>
sarray = sorted(range(len(text)), key = lambda i: text[i:])
MemoryError
还有其他代码,如:
sarray=[]
for i in range(len(text)):
sarray.append(text[i:])
order=[i[0] for i in sorted(enumerate(sarray), key=lambda x:x[1])]
print ", ".join([str(x) for x in order])
然而,这需要太多记忆,
s = 'AACGATAGCGGTAGA'
s = unicode(s,'utf-8','replace')
n = len(s)
sa = tks.simple_kark_sort(s)
lcp = tks.LCP(s,sa)
print n print sa
虽然它解决了这个问题,但是使用更大的字符串需要花费太多时间,...你知道其他库或改进后缀的方法吗?
答案 0 :(得分:6)
看起来你正在尝试构建一个后缀数组。幸运的是,这个算法已经有了Python实现:https://code.google.com/p/pysuffix/
如果您必须自己实现它,请考虑您的代码正在做什么:
range
制作与文本长度相同的整数列表。key
函数应用于列表的每个元素,并将结果存储在新列表中。(这也称为Schwartzian Transform,这是一个非常巧妙的想法。)
重点是,您正在为文本中的每个偏移创建一个(可能是大的)文本片段,并将其存储在新列表中。您将需要使用更专业的后缀数组构造算法来避免此成本。
最后,要解决你原来的问题:lambda表达式不是罪魁祸首。你只是碰上算法墙。
修改强>
这是快速SA算法的一个很好的资源: What's the current state-of-the-art suffix array construction algorithm?
答案 1 :(得分:5)
我怎么能改进行...所以当增加文本长度时我不会在lambda表达式上使用大量内存?
lambda表达式创建了一个简单的函数。很可能该函数的字节码大约是8个字节,并且围绕它的code
和function
对象的成本可能是80-128字节,具体取决于您的平台。一次只存在一个这样的函数,因此模块中的总内存开销为8个字节,而此函数运行时则为128个字节。
所以......什么也不做。
为了减少内存使用量,您必须使用大量内存找到实际 的代码部分,并减少它。特别是,您最有可能创建一个N个数字列表(range
),然后是另一个N个数字列表(sorted
)。您还可以瞬时创建N个N / 2长度的字符串,如果您使比较更加微妙,则不需要这些字符串。等等。不要那样做。
xrange
替换第一个列表。array.array
或NumPy ndarray
,这至少会消除每个号码的24-48字节“装箱”开销。i
和text
上,并具有根据需要引用text[i:]
的自定义比较运算符。然后在最坏的情况下,这些后缀中的两个将同时存在。str.join
(因为它会在您的背后创建一个列表),因此您需要一个不同的替代方案,例如将它们写入{ {1}}。或者,在您的情况下,因为您实际上没有返回任何内容,只需将其转储到stdout,然后逐个StringIO
将它们一个接一个地循环。