python列表生成/保存错误

时间:2014-01-21 18:10:32

标签: python list python-3.x combinations

我正在尝试制作能够打印azzz的所有可能组合的程序。我试图添加一个保存状态功能,它工作正常,但有这个错误。

假设我在打印e之类的内容时打断了程序。当我再次执行程序时,它会一直运行到z,但在z之后而不是打印aa它会打印ba并从ba继续。这也是在它打印zz之后发生的。它打印baa而不是aaa。我该如何解决这个问题?

这是我到目前为止所做的:

 import pickle,os,time

 alphabet="abcdefghijklmnopqrstuvwxyz"
 try:
     if os.path.isfile("save.pickle")==True:
         with open("save.pickle","rb") as f:
             tryn=pickle.load(f)
         for i in range(3):
             a=[x for x in alphabet]
             for j in range(i):
                 a=[x+i for x in alphabet for i in a]
             b=a[tryn:]
             for k in b:
                 print(k)
                 time.sleep(0.01)
                 tryn+=1
     else:
         tryn=0
         for i in range(3):
             a=[x for x in alphabet]
             for j in range(i):
                 a=[x+i for x in alphabet for i in a]
             for k in a:
                 print(k)
                 tryn+=1
                 time.sleep(0.01)
 except KeyboardInterrupt:
     with open("save.pickle","wb") as f:
         pickle.dump(tryn,f)

4 个答案:

答案 0 :(得分:2)

如果您使用python2或python3作为标记建议,那么它已存在于标准库中。有关解决此问题的简单方法,请参阅itertools,product py2product py3

答案 1 :(得分:1)

你的问题几乎肯定在这里:

a=[x for x in alphabet]
for j in range(i):
    a=[x+i for x in alphabet for i in a]

也许您不应该将循环中的值分配给a,而是使用不同的名称?否则,你每次都要改变你在循环中使用的内容......

编辑:更详细。所以,从技术上讲,user2357112的答案更为正确,但我正在修改我的。最初的答案只是快速阅读,所以另一个答案接近原意。但是,原始版本效率低(出于更多原因而不是使用产品:),因为您不止一次地生成内部循环。因此,让我们来看看为什么这是一个坏主意,作为一项教育活动:

初始算法:

for i in range(n):
    assign a to alphabet
    for j in range(i): 
        i times, we rewrite a to be all combinations of the current set against the alphabet.

注意,对于此算法,要生成长度(n)乘积,我们必须生成所有先前的乘积长度(n-1),长度(n-2),...,长度(1)。但是你没有拯救那些。

你最好做这样的事情:

sum_list = alphabet[:]
#get a copy
product_list = alphabet[:]
#Are we starting at 0, or 1? In any case, skip the first, since we preloaded it
for i in range(1, n):
    # Your existing list comprehension was equivalent here, and could still be used
    # it MIGHT be faster to do '%s%s'%(x,y) instead of x+y... but maybe not
    # with these short strings
    # This comprehension takes the result of the last iteration, and makes the next iteration
    product_list = [x+y for x,y in product(product_list, alphabet)]
    # So product list is JUST the list for range (n) - i.e. if we are on loop 2, this
    # is aaa...zzz. But you want all lengths together. So, as you go, add these
    # sublists to a main list.
    sum_list.extend(product_list)

总的来说,你的工作量很少。

结合其他事情:

  • 您使用i作为循环变量,然后在循环理解中重新使用它。这是相互矛盾的,可能不会像你期望的那样发挥作用。
  • 如果这是为了学习如何编写保存/恢复类型的应用程序......这不是一个好的。请注意,恢复功能正在重新计算每个值,以便能够从中断处返回 - 如果您可以重写此算法以将更多信息写入文件(例如product_list的当前值)和使它更像生成器,然后它实际上更像是一个真实世界的例子。

答案 2 :(得分:1)

  for i in range(3):
   a=[x for x in alphabet]
   for j in range(i):
    a=[x+i for x in alphabet for i in a]
   b=a[tryn:]

这是你的错误。您跳过每个长度的第一个tryn字符串,而不仅仅是第一个tryn字符串。如果不是以下内容,这将更容易在输出中识别:

   for k in b:
    print(k)
    time.sleep(0.01)
    tryn+=1

您修改tryn,即您正在跳过的内容。当您打印出长度为2的字符串时,您跳过的数字等于长度为1的字符串数。当你打印出长度为3的字符串时,你会跳过一些等于长度为2的字符串的数字。如果tryn大于长度为1的字符串数,则会跳过更多。

答案 3 :(得分:0)

以下是我建议如何在Python中解决此问题。我没有实现保存状态功能;这个序列不是很长,你的计算机应该能够非常快地生成这个序列,所以我认为不值得努力让它干净利落。

import itertools as it

def seq(alphabet, length):
    for c in range(1, length+1):
        for p in it.product(alphabet, repeat=c):
            yield ''.join(p)

alphabet="abcdefghijklmnopqrstuvwxyz"

for x in seq(alphabet, 3):
    print(x)

如果你真的想,你可以使用itertools制作单行。我觉得这很难阅读和理解;我更喜欢上面的版本。但由于使用itertools.chainitertools.imap()而不是Python for循环,这确实有效并且会更快一些。

import itertools as it

def seq(alphabet, length):
    return it.imap(''.join, it.chain.from_iterable(it.product(alphabet, repeat=c) for c in range(1, length+1)))

alphabet="abcdefghijklmnopqrstuvwxyz"

for x in seq(alphabet, 3):
    print(x)

在Python 3.x中,您可以使用map()而不是itertools.imap()