【问题标题】:Pythonic way of splitting loop over list in two parts with one iterator使用一个迭代器将列表上的循环拆分为两部分的 Pythonic 方法
【发布时间】:2018-03-16 13:09:55
【问题描述】:

我正在处理一个结构不规则的文本文件,该文件由标题和不同部分的数据组成。我的目标是遍历一个列表,一旦遇到某个角色就跳到下一部分。我在下面做了一个简单的例子。处理这个问题的优雅方法是什么?

lines = ['a','b','c','$', 1, 2, 3]

for line in lines:
    if line == '$':
        print("FOUND END OF HEADER")
        break
    else:
        print("Reading letters")

# Here, I start again, but I would like to continue with the actual
# state of the iterator, in order to only read the remaining elements.
for line in lines:
    print("Reading numbers")

【问题讨论】:

  • 你不能直接调用lines.index('$')来获取分隔符的位置吗?
  • 用例比这更复杂,我只是在寻找一种通用的方法。
  • 如果你发布你真正的问题而不是这个微不足道的问题,那将会很有成效
  • 真正的问题首先是一个标题、分隔符,然后是一组具有特定行数的任意部分。

标签: python list iterator


【解决方案1】:

实际上,您可以通过使用内置函数iter 在for 循环外创建行迭代器来为两个循环使用一个迭代器。这样它会在第一个循环中部分耗尽,并在下一个循环中重复使用。

lines = ['a','b','c','$', 1, 2, 3]

iter_lines = iter(lines) # This creates and iterator on lines

for line in iter_lines :
    if line == '$':
        print("FOUND END OF HEADER")
        break
    else:
        print("Reading letters")

for line in iter_lines:
    print("Reading numbers")

上面打印了这个结果。

Reading letters
Reading letters
Reading letters
FOUND END OF HEADER
Reading numbers
Reading numbers
Reading numbers

【讨论】:

  • 这是最python的答案。 +1
  • 这正是我想要的
【解决方案2】:

您可以使用enumerate 来跟踪您在迭代中的位置:

lines = ['a','b','c','$', 1, 2, 3]

for i, line in enumerate(lines):
    if line == '$':
        print("FOUND END OF HEADER")
        break
    else:
        print("Reading letters")

print(lines[i+1:]) #prints [1,2,3]

但是,除非您确实需要处理标题部分,否则@EdChum 的想法可能会更好地使用index

【讨论】:

    【解决方案3】:

    一种更简单的方法,也许更 Pythonic:

    lines = ['a','b','c','$', 1, 2, 3]
    print([i for i in lines[lines.index('$')+1:]])
    # [1, 2, 3]
    

    如果您想将$ 之后的每个元素读取到不同的变量,试试这个:

    lines = ['a','b','c','$', 1, 2, 3]
    a, b, c = [i for i in lines[lines.index('$')+1:]]
    print(a, b, c)
    # 1 2 3
    

    或者,如果您不知道$ 后面有多少元素,您可以这样做:

    lines = ['a','b','c','$', 1, 2, 3, 4, 5, 6]
    a, *b = [i for i in lines[lines.index('$')+1:]]
    print(a, *b)
    # 1 2 3 4 5 6
    

    【讨论】:

      【解决方案4】:

      如果您有不止一种分隔符,最通用的解决方案是构建一个迷你状态机来解析您的数据:

      def state0(line):
        pass # processing function for state0
      
      def state1(line):
        pass # processing function for state1
      
      # and so on...
      
      states = (state0, state1, ...)     # tuple grouping all processing functions
      separators = {'$':1, '#':2, ...}   # linking separators and states
      state = 0                          # initial state
      
      for line in text:
        if line in separators:
          print('Found separator', line)
          state = separators[line]       # change state
        else:
          states[state](line)            # process line with associated function
      

      此解决方案能够以任意重复次数以任意顺序正确处理任意数量的分隔符。唯一的限制是给定的分隔符后面总是跟同一种数据,这些数据可以由它的相关函数处理。

      【讨论】:

        猜你喜欢
        • 2012-01-30
        • 1970-01-01
        • 2011-03-31
        • 2015-02-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多