初学者Python:如何减少列表中的列表数量并优化以下程序

时间:2012-12-21 01:41:29

标签: performance list optimization memory-management python-2.7

我编写了以下程序,以生成我未来三年可能拥有的所有可能的时间表(我在季度系统上),但它的效率低得离谱,而且如上所述,不会让我得到答案。下一个百万年。

为了澄清,我确实已经编写了文本文件,指明了我感兴趣的课程以及每个季度的数字,学期和年份(例如2013-2014学年第1季度)。我想限制它来生成每季度4-5个班级的时间表,这有希望反映在该计划中。

我知道,考虑到所需结果的大小,我写的任何方式都会非常慢,但如果有人能帮助我加快速度,或者至少给我估计需要多长时间完成(24小时或24个月)我会非常感激。

我发现的两个问题,但我不知道如何解决,是:

  1. 我的比较功能(将列表转换为列表然后搜索列表中每个成员的另一个列表的每个成员)
  2. 一般来说广泛使用列表,根据我的研究是非常耗费内存的(例如,我使用的组合函数会产生一个迭代器对象,根据我的研究而不是列表应该更高效,但是我不知道如何有效地使用迭代器,从而如何减少内存使用;还有我在程序结束时使用的'GrandMasterLists'方法,结合所有双for循环和线性增加的调用次数比较每个for循环中的函数,还必须使它比它需要的效率低得多。
  3. 以下是很长的(177行)(尽管也是重复的)但如果您正在寻找挑战,或者如果您是编程专家,我将非常感激您的帮助。

    (我也意识到我在每一点上尝试做的很多事情可能都不是很透明 - 在很多方面我很难尝试提出符合我想做的代码 - 如果您需要澄清,请向我提问。)

    import itertools
    
    class Course:
        def __init__(self, NAME, TERM, YEAR):
            self.term=TERM
            self.year=YEAR
            self.name=NAME
    
    
    class Quarter:
        def __init__(self, NUMBER, TERM, YEAR):
            self.term=TERM
            self.year=YEAR
            self.number=NUMBER
    
    courselist=[]
    
    def coursegen(NAME, TERM, YEAR):
    
        return Course(NAME, TERM, YEAR)
    
    f=open('classlist.txt', 'r')
    for line in f:
        courselist.append(coursegen(line.rstrip().split(';')[0],line.rstrip().split(';')    [1].split(','),line.rstrip().split(';')[2].split(','))) 
    f.close()       
    
    def quartergen(NUMBER,TERM,YEAR):
        return Quarter(NUMBER,TERM,YEAR)
    
    m=open('quarterlist.txt', 'r')
    
    line1=m.readline()
    line2=m.readline()
    line3=m.readline()
    line4=m.readline()
    line5=m.readline()
    line6=m.readline()
    line7=m.readline()
    line8=m.readline()
    line9=m.readline()
    
    Quarter1=quartergen(line1.rstrip().split(';')[0],line1.rstrip().split(';')[1].split(','),line1.rstrip().split(';')[2].split(','))
    Quarter2=quartergen(line2.rstrip().split(';')[0],line2.rstrip().split(';')[1].split(','),line2.rstrip().split(';')[2].split(','))
    Quarter3=quartergen(line3.rstrip().split(';')[0],line3.rstrip().split(';')[1].split(','),line3.rstrip().split(';')[2].split(','))
    Quarter4=quartergen(line4.rstrip().split(';')[0],line4.rstrip().split(';')[1].split(','),line4.rstrip().split(';')[2].split(','))
    Quarter5=quartergen(line5.rstrip().split(';')[0],line5.rstrip().split(';')[1].split(','),line5.rstrip().split(';')[2].split(','))
    Quarter6=quartergen(line6.rstrip().split(';')[0],line6.rstrip().split(';')[1].split(','),line6.rstrip().split(';')[2].split(','))
    Quarter7=quartergen(line7.rstrip().split(';')[0],line7.rstrip().split(';')[1].split(','),line7.rstrip().split(';')[2].split(','))
    Quarter8=quartergen(line8.rstrip().split(';')[0],line8.rstrip().split(';')[1].split(','),line8.rstrip().split(';')[2].split(','))
    Quarter9=quartergen(line9.rstrip().split(';')[0],line9.rstrip().split(';')[1].split(','),line9.rstrip().split(';')[2].split(','))
    
    m.close()   
    
    def compare(x, y):
    
        if set(x).isdisjoint(set(y))==False:
        return True
    else:
            return False
    
    def offeredcoursegen(Quarter, courselist):
        offered=[]
    
        for course in courselist:
    
            if compare(course.year, Quarter.year)==True and compare(course.term, Quarter.term)==True:
    
                offered.append(course)
    
        return offered
    
    def combo(x, courselist):   
        return list(itertools.combinations(offeredcoursegen(x,courselist), 4))+list(itertools.combinations(offeredcoursegen(x,courselist), 5))
    
    Combo1=combo(Quarter1, courselist)
    
    Combo2=combo(Quarter2, courselist)
    
    Combo3=combo(Quarter3, courselist)
    
    Combo4=combo(Quarter4, courselist)
    
    Combo5=combo(Quarter5, courselist)
    
    Combo6=combo(Quarter6, courselist)
    
    Combo7=combo(Quarter7, courselist)
    
    Combo8=combo(Quarter8, courselist)
    
    Combo9=combo(Quarter9, courselist)
    
    GrandMasterList=[]
    
    for i in Combo1:
        for j in Combo2:
            if compare(i, j)==False:
                GrandMasterList.append([i,j])
    
    GrandMasterList2=[]
    
    for i in GrandMasterList:
        for j in Combo3:
            if compare(i[0],j)==False and compare(i[1],j)==False:
                GrandMasterList2.append(i+[j])
    
    GrandMasterList3=[]
    
    for i in GrandMasterList2:
        for j in Combo4:
            if compare(i[0],j)==False and compare(i[1],j)==False and    compare(i[2],j)==False:
                GrandMasterList3.append(i+[j])
    
    GrandMasterList4=[]
    
    for i in GrandMasterList3:
        for j in Combo5:
            if compare(i[0],j)==False and compare(i[1],j)==False and compare(i[2],j)==False and compare(i[3],j)==False:
                GrandMasterList4.append(i+[j])
    
    GrandMasterList5=[]
    
    for i in GrandMasterList4:
        for j in Combo6:
            if compare(i[0],j)==False and compare(i[1],j)==False and compare(i[2],j)==False and compare(i[3],j)==False and compare(i[4],j)==False:
                GrandMasterList5.append(i+[j])
    
    GrandMasterList6=[]
    
    for i in GrandMasterList5:
        for j in Combo7:
            if compare(i[0],j)==False and compare(i[1],j)==False and compare(i[2],j)==False and compare(i[3],j)==False and compare(i[4],j)==False and compare(i[5],j)==False:
                GrandMasterList6.append(i+[j])
    
    GrandMasterList7=[]
    
    for i in GrandMasterList6:
        for j in Combo8:
            if compare(i[0],j)==False and compare(i[1],j)==False and compare(i[2],j)==False and compare(i[3],j)==False and compare(i[4],j)==False and compare(i[5],j)==False and compare(i[6],j)==False:
                GrandMasterList7.append(i+[j])
    
    GrandMasterList8=[]
    
    for i in GrandMasterList7:
        for j in Combo9:
            if compare(i[0],j)==False and compare(i[1],j)==False and compare(i[2],j)==False and compare(i[3],j)==False and compare(i[4],j)==False and compare(i[5],j)==False and compare(i[6],j)==False and compare(i[7], j)==False:
                GrandMasterList8.append(i+[j])
    
    for i in range(len(GrandMasterList8)):
        print 'Schedule %d \n' % (i)
        print 'Quarter 1'
        for j in range(len(GrandMasterList8[i][0])):
        print '%s ' % (GrandMasterList8[i][0][j].name)
    print '\n Quarter 2'
    for j in range(len(GrandMasterList8[i][1])):
        print '%s ' % (GrandMasterList8[i][1][j].name)
    print '\n Quarter 3'
        for j in range(len(GrandMasterList8[i][2])):
            print '%s ' % (GrandMasterList8[i][2][j].name)
    print '\n Quarter 4'
        for j in range(len(GrandMasterList8[i][3])):
            print '%s ' % (GrandMasterList8[i][3][j].name)
        print '\n Quarter 5'
        for j in range(len(GrandMasterList8[i][4])):
            print '%s ' % (GrandMasterList8[i][4][j].name)
        print '\n Quarter 6'
        for j in range(len(GrandMasterList8[i][5])):
            print '%s ' % (GrandMasterList8[i][5][j].name)
        print '\n Quarter 7'
        for j in range(len(GrandMasterList8[i][6])):
            print '%s ' % (GrandMasterList8[i][6][j].name)
        print '\n Quarter 8'
        for j in range(len(GrandMasterList8[i][7])):
            print '%s ' % (GrandMasterList8[i][7][j].name)
        print '\n Quarter 9'
        for j in range(len(GrandMasterList8[i][8])):
            print '%s ' % (GrandMasterList8[i][8][j].name)
        print '\n \n \n'
    

2 个答案:

答案 0 :(得分:0)

@Joshua D. Boyd
这不是答案,但出于某种原因,我无法在评论中清楚地格式化classlist.txt的示例。
无论如何,这是一个例子:

德国209-0; S; 13-14,14-15,15-16
德国309-1; F; 14-15,15-16,16-17
德国309-2; W; 14-15,15-16,16-17
实分析1; F; 13-14,14-15,15-16,16-17
实分析2; W; 13-14,14-15,15-16,16-17
实分析3; S; 13-14,14-15,15-16,16-17
有机化学1; F; 13-14,14-15,15-16,16-17
有机化学2; W; 13-14,14-15,15-16,16-17
有机化学3; S; 13-14,14-15,15-16,16-17
微分几何; F; 13-14,14-15,15-16,16-17
STAT 383-0; W; 13-14,14-15,15-16,16-17
ECON 381-1; W; 13-14,14-15,15-16,16-17
MATH 325-0; W; 13-14,15-16

当然,整个列表大约有90个课程,程序必须通过这个课程来提出每个季度可用的大约10到20个课程,然后针对每个季度提出所有可能的课程组合,然后结合每个季度不重叠类别的组合(即所以我不会得到包含同一个类不止一次的结果)。

这是quarterlist.txt,如果这也有帮助:
1; F; 13-14
2; W; 13-14
3; S; 13-14
4; F; 14-15
5; W; 14-15
6; S; 14-15
7; F; 15-16
8; W; 15-16
9; S; 15-16

我希望这比以前更有帮助。当我在终端中使用python编译器运行上述程序时,甚至返回中间步骤需要很长时间(我在整个过程中插入了几个打印行来检查其进度,十分钟之后我只得到了'Combos')。考虑到预备步骤需要多长时间才能完成,理论上每个'GrandMasterList'的计算时间要比最后一个要长,至少我生成它们的方式,似乎这个程序需要花费不合理的长时间才能完成。

主要是我想提高效率:
比较功能
生成'GrandMasterList'的方法(即组合每个季度的所有类的组合,以便每个组合的类没有重叠)

答案 1 :(得分:0)

您发布的示例数据不够长,以至于需要很长时间。

您可以通过以下方式对您的计划进行分析:

python2.6 -m cProfile ./your_program.py

它会告诉你每个函数被调用的次数以及一堆其他统计信息。

在组合函数中,您将获取两个迭代器并将它们转换为列表以返回组合列表。如果你把combo重写为自己的迭代器,那可能会让你有所收获。

比较可以更简单地写为:

def compare(x, y):
    return not set(x).isdisjoint(set(y))