【问题标题】:Code doesn't print the last sequence in a file代码不打印文件中的最后一个序列
【发布时间】:2015-05-02 11:06:07
【问题描述】:

我有一个如下所示的文件:

<s0> 3
line1
line2
line3 
<s1> 5
line1
line2
<s2> 4
etc. up to more than a thousand

每个序列都有一个像&lt;s0&gt; 3 这样的标题,在这种情况下,它表示后面有三行。在上面的例子中,&lt;s1&gt;下面的行数是两行,所以我必须将标题更正为&lt;s1&gt; 2

我下面的代码挑选出序列标题和它们下面的正确行数。但是由于某种原因,它永远不会得到最后一个序列的细节。我知道出了点问题,但我不知道是什么。有人可以指出我做错了什么吗?

import re

def call():
with open('trial_perl.txt') as fp:
    docHeader = open("C:\path\header.txt","w")
    c = 0
    c1 = 0
    header = []
    k = -1
    for line in fp:
        if line.startswith("<s"):
            #header = line.split(" ")
            #print header[1]
            c = 0
        else:
            c1 = c + 1
            c += 1

        if c == 0 and c1>0:
            k +=1
            printing = c1
            if printing >= 0:
                s = "<s%s>" % (k)
            #print "%s %d" % (s, printing)

                docHeader.write(s+" "+str(printing)+"\n")

call()

【问题讨论】:

  • 非常感谢你们的投入,我真的很感激他们,他们帮助我的知识和理解,以及更多的逻辑思维。我已经能够通过在退出 for 循环时添加 docHeader.write(" %d\n" % (k+1, c1)) 来解决这个问题。有了你的投入,我的编码变得更好了!!!!!!!!!

标签: python algorithm file-io text-processing text-parsing


【解决方案1】:

您的数据中最后一个序列的末尾没有标记,因此您的代码需要在循环完成后处理最后一个序列。

【讨论】:

    【解决方案2】:

    如果我可以建议一些 python 技巧来获得你的结果;您不需要那些 c/c1/k 计数器变量,因为它们使代码更难阅读和维护。相反,将序列标题映射到序列项,然后使用该映射完成所有工作:

    (此代码仅在所有序列头都是唯一的情况下才有效 - 如果您有重复,它将不起作用)

    with open('trial_perl.txt') as fp:
        docHeader = open("C:\path\header.txt","w")
        data = {}
        for line in fp:
            if line.startswith("<s"):
                current_sequence = line
                # create a list with the header as the key
                data[current_sequence] = []
            else:
                # add each sequence to the list we defined above
                data[current_sequence].append(line)
    

    您的地图已准备就绪!它看起来像这样:

    {"<s0> 3": ["line1", "line2", "line5"],
     "<s1> 5": ["line1", "line2"]}
    

    你可以这样迭代它:

    for header, lines in data.items():
        # header is the key, or "<s0> 3"
        # lines is the list of lines under that header ["line1", "line2", etc]
        num_of_lines = len(lines)
    

    【讨论】:

      【解决方案3】:

      主要问题是您在阅读最后一行后忽略了检查c 的值。由于所有多余的代码,您可能很难发现这个问题。您不必增加k,因为您可以从&lt;s...&gt; 标记中提取值。而且您不必拥有所有三个变量cc1printing。一个 count 变量就可以了。

      import re, sys
      
      def call():
          with open('trial_perl.txt') as fp:
              docHeader = sys.stdout #open("C:\path\header.txt","w")
              count = 0
              id = None
              for line in fp:
                  if line.startswith("<s"):
                      if id != None:
                          tag = '<s%s>' % id
                          docHeader.write('<s%d> %d\n' % (id, count))
                      count = 0
                      id = int(line[2:line.find('>')])
                  else:
                      count += 1
              if id != None:
                  tag = '<s%s>' % id
                  docHeader.write('<s%d> %d\n' % (id, count))
      
      call()
      

      【讨论】:

      • 嗨@Laszlo,我没有完全得到你的代码的输出。我增加 K,因为每个序列头之后的值并不总是正确的。所以我需要确保通过计数来获得当前的行数。
      • 我增加count 来跟踪行数。您使用 k 作为标题编号,但我直接从标题中提取它。这就是为什么我不需要k
      • 另外,你注意到我使用sys.stdout 来验证输出了吗?如果您希望将输出写入“header.txt”,则必须将该行改回docHeader = open("C:\path\header.txt","w")
      【解决方案4】:

      另一种使用来自 itertools 的 groupby 的方法,您在每个组中获取最大行数 - 一个组对应于文件中的标题 + 行序列::

      from itertools import groupby
      
      def call():
          with open('stack.txt') as fp:
              header = [-1]
              lines  = [0]
              for line in fp:
                  if line.startswith("<s"):
                      header.append(header[-1]+1)
                      lines.append(0)
                  else:
                      header.append(header[-1])
                      lines.append(lines[-1] +1)
      
          with open('result','w') as f:
              for key, group in groupby(zip(header[1:],lines[1:]), lambda x: x[0]):
                  f.write(str(("<s%d> %d\n" % max(group))))
      
          f.close()
      
      call()
      
      #<s0> 3
      #<s1> 2
      

      stack.txt 是包含您的数据的文件:

      <s0> 3
      line1
      line2
      line3 
      <s1> 5
      line1
      line2
      

      【讨论】:

      • 您好上校,无法打印输出
      • @Ebuka我的意思是粘贴并让我的代码运行什么都不出现吗?我忘了提到我在终端中使用命令python myscript.py 运行它
      • 我不知道您如何运行代码(使用编辑器 + 控制台,或直接在 Python 控制台中,或使用和 IDE)。我更新了代码,以便将结果保存在 result 文件中,与您的脚本位于同一文件夹中。
      猜你喜欢
      • 2012-10-14
      • 1970-01-01
      • 2019-04-15
      • 2015-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-15
      相关资源
      最近更新 更多