【问题标题】:How to start checking from specific part of a list in python如何从python中列表的特定部分开始检查
【发布时间】:2026-01-04 11:00:01
【问题描述】:

鉴于以下列表:

#123
*21
*23
*56
*1
*3
#923
*21
*23
*56
*1
*3
#165
...

我想先用#找到具体的行

例如:#923

然后打印所有以 * 为前缀的数字,直到下一次出现以 # 开头的行。

这是我尝试过的,但它不起作用:

for i in data:
     ndata = i.split("::")
     check = list(ndata[0])
     if check[0] == '*':
        songs += ndata[0] + "\n"
     if check[0] == '#':
        break

它会打印 * 并在以 # 开头的行上换行,但问题是它从第一行开始,而不是从包含 #923 的行开始。

我将不胜感激任何帮助和提示!

【问题讨论】:

    标签: python list arraylist


    【解决方案1】:

    您可以使用itertools.dropwhile 删除行,直到到达您想要的行,然后循环直到找到以# 开头的行

    from itertools import dropwhile   
    def section(fle, start, stop):
        with open(fle) as f:
            # consume lines until we get to our start line
            drop = dropwhile(lambda x: x.strip() != start, f)
            # skip start
            next(drop, "")
            # loop starting at line after start line
            for line in drop:
                # if we reach stop line break
                if line.startswith(stop):
                    break
                # else we just yield the line
                yield line.rstrip()
    

    输出:

    In [4]: list(section("in.txt", "#923", "#"))
    Out[4]: ['*21', '*23', '*56', '*1', '*3']
    

    适用于从 start 开始并由以 # 开头的行分隔的多个部分:

    from itertools import dropwhile, groupby
    
    
    def section(fle, start, end):
        with open(fle) as f:
            grps = groupby(dropwhile(lambda x: x.strip() != start, f),
                           key=lambda x: x.startswith(end))
            for k, v in grps:
                if not k:
                    yield list(map(str.strip,v))
    

    演示:

    n [13]: cat in.txt
    (4.471719725275173E-003,2.163649191486555E-002)
    (6.471719725275173E-003,2#123
    *21
    *23
    *56
    *1
    *3
    #923
    *21
    *23
    *56
    *1
    *3
    #165.163649191486555E-002)
    *210
    *230
    *560
    *10
    *30
    #165.163649191486555E-002)
    In [14]: list(section("in.txt", "#923", "#"))
    Out[14]: [['*21', '*23', '*56', '*1', '*3'], ['*210', '*230', '*560', '*10', '*30']]
    

    【讨论】:

      【解决方案2】:

      可能是这样的:

      data = ( "#123", "*21", "*23", "*56", "*1", "*3", "#923", "*21", "*23", "*56", "*1", "*3", "#16a" )
      
      for idx,num in enumerate(data):
          if num == "#923":
              break
          #
      #
      for num in data[idx + 1:]:
          if num[0] == '#':
              break;
          #
          print num
      #
      

      给予:

      *21
      *23
      *56
      *1
      *3
      

      【讨论】:

        【解决方案3】:

        请注意,在找到 #923 之前,您不会抑制输出,也不会对其进行测试。因此,您将拾取找到的第一个 #。

        请注意,您的 for 循环显示 for i in data:,其中包括第一行。您需要有一个标志来确定这是第一次还是第二次。请注意,第一次进入循环时,您测试的第一个条目是 # 条目,因此您将中断。

        你应该做的(而不是休息)是创建一个新的歌曲列表,每次你得到新的#条目。将每首 * 歌曲附加到列表中。然后你会得到一个歌曲列表。

        既然你有它,你将歌曲视为一个字符串,你从未初始化它,所以添加到字符串 songs += ndata[0] = "\n 将失败。

        此外,数据中的最后一行是否会是 #(这会在末尾创建一个空歌曲列表)?如果你只是添加到一个字符串,它会自行退出。

        如果您想每次都创建一个单独的歌曲列表,请使用带有 yield 而不是返回歌曲列表(或字符串)的生成器

        【讨论】:

          【解决方案4】:

          没有必要让事情变得比实际更复杂。只需使用两个for 循环:

          with open(yourFile) as fp:
          
              for line in fp:
                  if line.startswith('#923'):
                      break
          
              for line in fp:
                  if line.startswith('#'):
                      break
                  if line.startswith('*'):
                      print line
          

          如果你的数据已经是一个列表,那么:

              it = iter(yourList)
          
              for line in it:
                  if line.startswith('#923'):
                      break
          
              for line in it:
                  if line.startswith('#'):
                      break
                  if line.startswith('*'):
                      print line
          

          【讨论】: