【问题标题】:Python memory error when searching substring搜索子字符串时出现Python内存错误
【发布时间】:2015-11-21 07:08:38
【问题描述】:

我正在尝试查找非常大字符串的子字符串并出现内存错误:

代码:

def substr(string):
    le = []
    st = list(string)
    for s in xrange(len(string)+1):
        for s1 in xrange(len(string)+1):
            le.append(''.join(st[s:s1]))

    cou = Counter(le)
    cou_val = cou.keys()
    cou_val.remove('')
    return le, cou_val

在 substr 中,第 31 行的 ile "solution.py" 出现错误 le.append(''.join(st[s:s1])) 内存错误

如何解决这个问题?

【问题讨论】:

标签: python memory


【解决方案1】:

回答

我注意到您的代码以特定顺序打印所有可能的字符串子字符串。我建议不要将它们全部存储在一个数组中,而是使用代码只返回你想要的子字符串。我用“很长的字符串”测试了下面的子例程,它总是返回相同的值,就好像你要从数组中获取索引值一样。

    string = 'a very long string'
    def substr2(string,i):
        return string[i//(len(string)+1):i%(len(string)+1)]

    print(substr2(string,10))

解决方案

为 for 循环 (s,s1) 排序参数的方式类似于数字系统。 s1 递增 1 直到达到给定值,然后重置为 0 并且 s 递增 1,重复循环。这在十进制系统中可见(例如 01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16 等)

i//n div 运算符返回 i/n 的整数值。 (例如 14//10=1)。 i%n mod 运算符返回 i/n 的余数。 (例如 14%10 是 4)。

因此,例如,如果我们将 i 加 1 并将 (s,s1) 定义为 [i//10,i%10],我们将得到:

[0,0],[0,1],[0,2],[0,3],[0,4],[0,5],[0,6],[0,7] ,[0,8],[0,9],[1,0],[1,1],[1,2] 等。

我们可以利用这些来产生与您的数组中相同的答案。

附言。我的第一个答案。希望这会有所帮助!

【讨论】:

  • +1:好主意和好答案:)。您还可以通过循环 substr2yeald 而不是 return 将上述内容编写为生成器。
【解决方案2】:

您似乎内存不足。当string 太大时,您发布的代码似乎会一遍又一遍地将其复制到le 列表中。正如@Rikka 的链接所示,buffer/memoryview 可能对您有用,但我从未使用过。

作为解决方案/代码的解决方法,我建议不要将每个子字符串存储在 le 中,而是将索引存储为元组。此外,我认为不需要 st 列表(不确定您的方式是否加快了速度),因此结果将是(代码未测试):

def substr(string):
    le = []

    for s in xrange(len(string)+1):
        for s1 in xrange(len(string)+1):
            # Skip empty strings
            if s!=s1:
                le.append((s, s1))

    cou = Counter(le)
    cou_val = cou.keys()
    cou_val.remove('')
    return le, cou_val

现在,如何使用substr 的示例是(代码未测试):

myString = "very long string here"
matchString = "here"
matchPos = False
indexes, count = substr(myString)

# Get all the substrings without storing them simultaneously in memory
for i in indexes:
    # construct substring and compare
    if myString[i[0],i[1]]==matchString:
        matchPos = i
        break

在上面之后,您将第一次出现“here”的开始和结束位置放入您的大字符串中。我不确定您尝试实现什么,但这可以轻松修改以查找所有出现、计数匹配等 - 我只是将其作为示例发布。我也不确定为什么有Counter...

这种方法不应该出现内存错误,但是,它是内存和 CPU 之间的权衡,我希望它在运行时会慢一些,因为每次使用 indexes 时都必须重新构造每个子字符串.

希望对你有帮助

【讨论】:

    【解决方案3】:

    解决办法: 内存中的错误总是由超出范围引起的。切片技术也有一些规则。 step 为正时,如 1,第一个索引必须大于第二个。反之,当为负数时,如 -1,索引的个数比第二个短,但实际上更大一。(-1 > -2) 所以在你的程序中,当step为1时,索引s大于s1,所以你访问了一个你没有申请的地方。你知道,那就是MemoryError!!!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多