Python 需要更有效的循环嵌套解决方案

Python 需要更有效的循环嵌套解决方案,python,loops,for-loop,nested,Python,Loops,For Loop,Nested,我试图比较两个文件。我将列出两个文件内容: File 1 File 2 "d.complex.1" "d.complex.1" 1 4 5 5 48 47 65

我试图比较两个文件。我将列出两个文件内容:

 File 1                           File 2

"d.complex.1"                     "d.complex.1"

  1                                 4
  5                                 5
  48                                47
  65                                21

d.complex.10                    d.complex.10

  46                                5
  21                                46
 109                               121
 192                               192
每个文件中总共有2000个d.complex。我试图比较这两个文件,但问题是第一个文件中的d.complex.1下列出的值必须与第二个文件中的所有2000个d.complex条目进行检查,如果条目不匹配,则将其打印出来。例如,在上述文件中,在file1 d.complex.1中,file2 d.complex.1中不存在数字48;因此,该编号必须存储在列表中(稍后打印)。然后,同样的d.complex.1必须与文件2的d.complex.10进行比较,并且由于1、48和65不存在,因此必须将它们附加到列表中

我选择的方法是使用集合,然后进行交集。我写的代码是:

first_complex=open( "file1.txt", "r" )
first_complex_lines=first_complex.readlines()
first_complex_lines=map( string.strip, first_complex_lines )
first_complex.close()

second_complex=open( "file2.txt", "r" )
second_complex_lines=second_complex.readlines()
second_complex_lines=map( string.strip, second_complex_lines )
second_complex.close()


list_1=[]
list_2=[]

res_1=[]
for line in first_complex_lines:
    if line.startswith( "d.complex" ):
        res_1.append( [] )
    res_1[-1].append( line )

res_2=[]
for line in second_complex_lines:
    if line.startswith( "d.complex" ):
        res_2.append( [] )
    res_2[-1].append( line )
h=len( res_1 )
k=len( res_2 )
for i in res_1:
   for j in res_2:
       print i[0]
       print j[0]
       target_set=set ( i )
       target_set_1=set( j )
       for s in target_set:
           if s not in target_set_1:
               print s
上面的代码给出了如下输出(只是一个示例):

109 d、 复杂1.1.dssp d、 复杂1.1.dssp d、 复杂。10.dssp

虽然上面的答案是正确的,但我想要一种更有效的方法,有人能帮我吗?此外,还打印了两个d.complex.1.dssp,而不是一个也不好的

我想要的是:

d.complex.1
d.complex.1 (name from file2)
   1
   48
   65

d.complex.1
d.complex.10 (name from file2)
   1
   48
   65
我对python非常陌生,所以我上面的概念可能有缺陷。此外,我以前从未使用过sets:(.有人能帮我一下吗?

指针:

  • 使用列表理解或生成器表达式简化数据处理。更具可读性
  • 只需生成一次集合
  • 使用函数避免重复自己的任务,尤其是重复两次相同的任务
我对您的输入数据做了一些假设,您可能希望尝试类似的方法

def parsefile(filename):
  ret = {}
  cur = None
  for line in ( x.strip() for x in open(filename,'r')):
    if line.startswith('d.complex'):
      cur = set()
      ret[line] = cur
    if not cur or not line.isdigit():
      continue
    cur.add(int(line))
  return ret

def compareStructures(first,second):
  # Iterate through key,value pairs in first
  for firstcmplx, firstmembers in first.iteritems():
    # Iterate through key,value pairs in second
    for secondcmplx, secondmembers in second.iteritems():
      notinsecond = firstmembers- secondmembers
      if notinsecond:
        # There are items in first that aren't in second
        print firstcmplx
        print secondcmplx
        print "\n".join([ str(x) for x in notinsecond])

first = parsefile("myFirstFile.txt")
second = parsefile("mySecondFile.txt")

compareStructures(first,second)

为修复而编辑..显示了我对运行代码进行测试的依赖程度:)谢谢Alex

已经有了一个很好的答案,由@MattH提供,重点是问题的Python细节,虽然可以在几个细节上进行改进,但改进只会使您的效率提高一些百分点--值得,但不是很好

效率大幅提升的唯一希望(与“kai zen”增量改进相反)是算法的剧烈变化——这可能是可能的,也可能是不可能的,这取决于您未披露的数据的特征,以及关于您的精确需求的一些细节

关键部分是:大概,文件中会出现多少数字,大概每个“d.complex.N”节有多少数字?你已经告诉我们每个文件大约有2000节(当然这也是很重要的),并且印象是在每个文件中,它们将按连续递增的N--1,2,3,等等排序(是这样吗?)

您的算法构建了两个映射节->数字(效率不高,但@MattH的答案重点在于增强这一点),因此不可避免地需要
N平方
节到节检查——因为N是2000,它需要400万这样的检查

考虑构建反向的地图、数字->节——如果一节中的数字范围和数字的典型大小都受到合理限制,那么它们将更加紧凑。例如,如果数字在1到200之间,并且每节大约有4个数字,这意味着一个数字通常在
(2000*4)/200
->->40节中,因此这样的映射将有200个条目,每个条目大约有40节。它只需要200个平方(40000)检查,而不是400万,就可以获得每个数字的联合信息(然后,根据对输出格式的确切需要,格式化该信息可能需要再次进行大量的工作——如果您最终绝对需要400万个“节对”作为输出,那么当然没有办法避免400万“输出操作,这将不可避免地非常昂贵)

但所有这些都取决于您没有告诉我们的数字——平均节数、文件中的数字范围,以及您必须绝对遵守的输出格式约束的细节(如果这些数字是合理的,那么输出格式约束将是影响任何程序的big-O性能的关键约束)

请记住,引用:

给我看看你的流程图,然后隐藏 你的桌子,我将继续 让我看看你的桌子,然后 我通常不需要你的流程图; 这是显而易见的


布鲁克斯是在60年代写作的(尽管他的散文集《神秘的人月》在70年代后期出版),其中使用了“流程图”(我们称之为代码或算法)和“表格”(我们称之为数据或数据结构)--但一般概念仍然非常有效:在所有专注于数据处理的程序(如您的)中,数据的组织和性质可能比代码的组织更重要,特别是因为它限制了后者;-).

您正在请求帮助解析文件。为了帮助您解析文件,最有用的是了解输入的确切格式。而不是像您提供的那样在列中并排显示两个文件。“d.complex”的出现之间是否有一条空行?这不是与您最近的问题相同吗?”“无法使集合交集工作”?@MattH,概念不错,但您应该清理细节——例如,您创建了data1和data2,但随后通过了名为first和second的东西,测试
if len(notinsecond):
你应该在哪里测试呢?
如果没有问题的话:
等等--值得编辑来解决这些问题!@Alex Martelli,谢谢你的校对!当我把它放在一起的时候是多任务的,因为我没有合理的样本输入数据,所以我没有测试它。我通常会回顾我自己的答案,但没有时间。
def parsefile(filename):
  ret = {}
  cur = None
  for line in ( x.strip() for x in open(filename,'r')):
    if line.startswith('d.complex'):
      cur = set()
      ret[line] = cur
    if not cur or not line.isdigit():
      continue
    cur.add(int(line))
  return ret

def compareStructures(first,second):
  # Iterate through key,value pairs in first
  for firstcmplx, firstmembers in first.iteritems():
    # Iterate through key,value pairs in second
    for secondcmplx, secondmembers in second.iteritems():
      notinsecond = firstmembers- secondmembers
      if notinsecond:
        # There are items in first that aren't in second
        print firstcmplx
        print secondcmplx
        print "\n".join([ str(x) for x in notinsecond])

first = parsefile("myFirstFile.txt")
second = parsefile("mySecondFile.txt")

compareStructures(first,second)