使用itertools.combinations生成对时的Python内存错误

时间:2013-09-20 00:14:47

标签: python list compiler-errors out-of-memory

我有一个带有未指定编号的int列表。我想找到列表中与某个值匹配的两个整数之间的区别。

from itertools import combinations

#Example of a list
intList = [3, 6, 2, 7, 1]
diffList = [abs(a -b) for a, b in combinations(intList, 2)]

#Given if difference = 2    
print diffList.count(2)

代码片段工作但是当给出更大的列表时,我得到了MemoryError。任何人都可以告诉我代码是否有问题或错误是由于我的硬件限制?

3 个答案:

答案 0 :(得分:4)

“更大的名单”究竟有多大?如果len(intList)n,则len(diffList)将为n*(n-1)//2(一次2个n项的组合数量。如果n足够大,这将消耗所有内存。

如果您只关心值2,

print sum(abs(a-b) == 2 for a, b in combinations(intList, 2))

是一种方法,无论intList有多大,都会消耗很少的内存。但是,它仍然需要时间len(intList)的平方成比例。

答案 1 :(得分:3)

您可以使用以下代码解决问题:

result = 0
for a, b in combinations(intList, 2):
    if abs(a - b) == 2:
        result += 1
print result

因此,您的问题不仅仅是硬件限制,而是硬件限制和错误代码。

答案 2 :(得分:3)

您创建了一个包含列表推导的列表,然后调用其count方法。相反,只需创建一个带有生成器表达式的迭代器,然后调用一个icount函数,它接受任何迭代:

diffs = (abs(a -b) for a, b in combinations(intList, 2))
print icount(diffs, 2)

它与原始代码几乎完全相同,但它不使用任何额外的内存。


当然icount函数不存在,但您应该能够自己编写。

def icount(iterable, value):
    result = 0
    for element in iterable:
        if element == value:
            result += 1
    return result

......或......

def ilen(iterable):
    return sum(1 for _ in iterable)
def icount(iterable, value):
    filtered = (elem for elem in iterable if elem == value)
    return ilen(filtered)

......或......

def icount(iterable, value):
    return sum(elem == value for elem in iterable)

...或(使用itertools recipes)...

def icount(iterable, value):
    return quantify(iterable, lambda elem: elem == value)

如果你愿意,你可以将表达式合并到icount函数中并在一行中完成所有操作,然后你就得到Tim Peters的答案。