python - 有效地连接大列表元素

标签 python python-itertools

我想制作一个元素列表,其中每个元素以 4 个数字开头,以 4 个字母结尾,并包含所有可能的组合。这是我的代码

import itertools

def char_range(c1, c2):
    """Generates the characters from `c1` to `c2`"""
    for c in range(ord(c1), ord(c2)+1):
        yield chr(c)


chars =list()
nums =list()
for combination in itertools.product(char_range('a','b'),repeat=4):
        chars.append(''.join(map(str, combination)))

for combination in itertools.product(range(10),repeat=4):
        nums.append(''.join(map(str, combination)))

c = [str(x)+y for x,y in itertools.product(nums,chars)]
for dd in c:
        print(dd)

这运行良好,但是当我使用更大范围的字符时,例如 (a-z),程序会占用 CPU 和内存,并且 PC 变得无响应。那么我怎样才能以更有效的方式做到这一点呢?

最佳答案

itertools 的文档说“它大致相当于生成器表达式中的嵌套 for 循环”。所以 itertools.product 永远不是内存的敌人,但如果你将它的结果存储在一个列表中,那么这个列表就是。因此:

for element in itertools.product(...):
    print element

没关系,但是

myList = [element for itertools.product(...)]

或等效的循环

for element in itertools.product(...):
    myList.append(element)

不是!因此,您希望 itertools 为您生成结果,但您不想存储它们,而是在生成结果时使用它们。想想你的这行代码:

c = [str(x)+y for x,y in itertools.product(nums,chars)]

鉴于 nums 和 chars 可能是巨大的列表,在它们之上构建另一个包含所有组合的巨大列表肯定会阻塞您的系统。

现在,如评论中所述,如果您用生成器替换所有太胖而无法放入内存的列表(仅产生的函数),内存将不会成为问题不再。

这是我的完整代码。我基本上将您的 chars 和 nums 列表更改为生成器,并摆脱了 c 的最终列表。

import itertools

def char_range(c1, c2):
    """Generates the characters from `c1` to `c2`"""
    for c in range(ord(c1), ord(c2)+1):
        yield chr(c)

def char(a):
    for combination in itertools.product(char_range(str(a[0]),str(a[1])),repeat=4):
        yield ''.join(map(str, combination))

def num(n):
    for combination in itertools.product(range(n),repeat=4):
        yield ''.join(map(str, combination))

def final(one,two):
    for foo in char(one):
        for bar in num(two):
            print str(bar)+str(foo)

现在让我们问一下 ['a','b'] 和 range(2) 的每个组合是什么:

final(['a','b'],2)

产生这个:

0000aaaa
0001aaaa
0010aaaa
0011aaaa
0100aaaa
0101aaaa
0110aaaa
0111aaaa
1000aaaa
1001aaaa
1010aaaa
1011aaaa
1100aaaa
1101aaaa
1110aaaa
1111aaaa
0000aaab
0001aaab
0010aaab
0011aaab
0100aaab
0101aaab
0110aaab
0111aaab
1000aaab
1001aaab
1010aaab
1011aaab
1100aaab
1101aaab
1110aaab
1111aaab
0000aaba
0001aaba
0010aaba
0011aaba
0100aaba
0101aaba
0110aaba
0111aaba
1000aaba
1001aaba
1010aaba
1011aaba
1100aaba
1101aaba
1110aaba
1111aaba
0000aabb
0001aabb
0010aabb
0011aabb
0100aabb
0101aabb
0110aabb
0111aabb
1000aabb
1001aabb
1010aabb
1011aabb
1100aabb
1101aabb
1110aabb
1111aabb
0000abaa
0001abaa
0010abaa
0011abaa
0100abaa
0101abaa
0110abaa
0111abaa
1000abaa
1001abaa
1010abaa
1011abaa
1100abaa
1101abaa
1110abaa
1111abaa
0000abab
0001abab
0010abab
0011abab
0100abab
0101abab
0110abab
0111abab
1000abab
1001abab
1010abab
1011abab
1100abab
1101abab
1110abab
1111abab
0000abba
0001abba
0010abba
0011abba
0100abba
0101abba
0110abba
0111abba
1000abba
1001abba
1010abba
1011abba
1100abba
1101abba
1110abba
1111abba
0000abbb
0001abbb
0010abbb
0011abbb
0100abbb
0101abbb
0110abbb
0111abbb
1000abbb
1001abbb
1010abbb
1011abbb
1100abbb
1101abbb
1110abbb
1111abbb
0000baaa
0001baaa
0010baaa
0011baaa
0100baaa
0101baaa
0110baaa
0111baaa
1000baaa
1001baaa
1010baaa
1011baaa
1100baaa
1101baaa
1110baaa
1111baaa
0000baab
0001baab
0010baab
0011baab
0100baab
0101baab
0110baab
0111baab
1000baab
1001baab
1010baab
1011baab
1100baab
1101baab
1110baab
1111baab
0000baba
0001baba
0010baba
0011baba
0100baba
0101baba
0110baba
0111baba
1000baba
1001baba
1010baba
1011baba
1100baba
1101baba
1110baba
1111baba
0000babb
0001babb
0010babb
0011babb
0100babb
0101babb
0110babb
0111babb
1000babb
1001babb
1010babb
1011babb
1100babb
1101babb
1110babb
1111babb
0000bbaa
0001bbaa
0010bbaa
0011bbaa
0100bbaa
0101bbaa
0110bbaa
0111bbaa
1000bbaa
1001bbaa
1010bbaa
1011bbaa
1100bbaa
1101bbaa
1110bbaa
1111bbaa
0000bbab
0001bbab
0010bbab
0011bbab
0100bbab
0101bbab
0110bbab
0111bbab
1000bbab
1001bbab
1010bbab
1011bbab
1100bbab
1101bbab
1110bbab
1111bbab
0000bbba
0001bbba
0010bbba
0011bbba
0100bbba
0101bbba
0110bbba
0111bbba
1000bbba
1001bbba
1010bbba
1011bbba
1100bbba
1101bbba
1110bbba
1111bbba
0000bbbb
0001bbbb
0010bbbb
0011bbbb
0100bbbb
0101bbbb
0110bbbb
0111bbbb
1000bbbb
1001bbbb
1010bbbb
1011bbbb
1100bbbb
1101bbbb
1110bbbb
1111bbbb

这正是您要查找的结果。此结果的每个元素都是动态生成的,因此永远不会产生内存问题。您现在可以尝试并了解 final(['a','z'],10) 等更大的操作对 CPU 友好。

关于python - 有效地连接大列表元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47971684/

相关文章:

Python 程序将无法正确运行

python - 如何使用 itertools 按名称分组、保留键和名称?

python - 如何使用Python正确复制 ".xlsx"文件

python - 使用 itertools 的排列爆炸内存

python - 将提取代码添加到 beautifulsoup 循环

python - pandas DataFrame 列中重复值的顺序

python - 如何按总和的顺序遍历大量整数元组?

列表中的 Python 大写元素(使用 Itertools?)

python - 如何从 openerp 中的帐户报告打印单一合作伙伴分类帐报告

python - 对非常大的 Pandas Data frame 进行聚合和统计