1

Hi stackoverflow Users,

I am wondering how to use for loop with string.

For example,

There is a file (file.txt) like,

=====================

Initial Value

    1 2 3
    3 4 5
    5 6 7

Middle Value           <---From Here

    3 5 6
    5 8 8
    6 9 8                  <---To Here

Last Value

    5 8 7
    6 8 7
    5 5 7

==================

I want to modify the section of the file only in "Middle Value" and write an output file

after modifying.

I think that if I use "if and for" statements, that might be solved.

I have thought a code like

with open('file.txt') as f, open('out.txt', 'w') as f2:

       for line in f:
           sp1 = line.split()
           line = " ".join(sp1) + '\n'
           if line == 'Middle':
              "Do something until line == 'Last'"

I am stuck with "Do something until line == 'Last'" part.

Any comments are appreciated.

Thanks.

4

5 回答 5

3

有三种基本方法。


首先是使用状态机。您可以构建一个真实的状态机,但在这种情况下,状态和转换非常简单,只需使用一个标志就可以更简单地伪造它:

state = 0
for line in f:
    sp1 = line.split()
    line = " ".join(sp1) + '\n'
    if state == 0:
        if line == 'Middle\n':
            state = 1
    elif state == 1:
        if line == 'Last\n':
            state = 2
        else:
            # Thing you do until line == 'Last\n'
    else:
        # nothing to do after Last, so you could leave it out

请注意,我检查了'Middle\n',而不是'Middle'。如果您查看line上面的构建方式,它无法匹配后者,因为您总是添加'\n'. 但还要注意,在您的示例数据中,该行是'Middle Value\n', not 'Middle',所以如果在您的真实数据中是这样,您必须在此处处理。是line == 'Middle Value\n',line.startswith('Middle')还是其他取决于您的实际数据,只有您自己知道。


或者,您可以将其分解为循环:

for line in f:
    sp1 = line.split()
    line = " ".join(sp1) + '\n'
    if line == 'Middle\n':
        break
for line in f:
    sp1 = line.split()
    line = " ".join(sp1) + '\n'
    if line == 'Last\n':
        break
    else:
        # Thing you do until line == 'Last\n'
for line in f:
    # Nothing to do here, so you could leave the loop out

这一个也有变化。例如:

lines = (" ".join(line.split()) + '\n' for line in f)
lines = dropwhile(lambda line: line != 'Middle', lines)
middle = takewhile(lambda line: line != 'End', lines)
for line in middle:
    # Thing you want to do

最后,您可以在将文件转换为行之前拆分文件,而不是之后。这很难迭代完成,所以让我们将整个文件读入内存来展示这个想法:

contents = f.read()
_, _, rest = contents.partition('\nMiddle\n')
middle, _, _ = rest.partition('\nEnd')
for line in middle.splitlines():
    # Thing you want to do

如果将整个文件读入内存会浪费太多空间或在开始之前花费太长时间,那mmap是你的朋友。

于 2013-07-12T17:51:11.117 回答
1

我只是将这个过程编码为一个简单的 FSM(有限状态机或更具体地说是事件驱动的有限状态机):

with open('file.txt') as f, open('out.txt', 'w') as f2:
    state = 1
    for line in f:
        if line == 'Middle Value\n':
            state = 2
            continue  # unless there's something to do upon entering the state
        elif line == 'Last Value\n':  # might want to just test for blank line `\n'
            state = 3
            continue  # unless there's something to do upon entering the state

        # otherwise process to line based on the current value of "state"
        if state == 1:      # before 'Middle Value' has been seen
            pass
        elif state == 2:    # after 'Middle Value' has been seen
            pass
        else:               # after 'Last Value' (or a blank line after 
            pass            # 'Middle Value') has been seen

只需将这些pass语句替换为在读取输入文件时适合做的任何事情。

于 2013-07-12T18:14:12.550 回答
0

请原谅我访问文件的方式有点不同

with open('file.txt') as f:
    file_string = f.read()

middle_to_end = file_string.split('Middle Value\n')[-1]
just_middle   = middle_to_end.split('Last Value\n')[0]

middle_lines = just_middle.splitlines()
for line in middle_lines:
    do_something
于 2013-07-12T17:50:49.117 回答
0

在你的if line == 'Middle':你可以翻转一个布尔标志,允许你输入另一个if inMiddle and line !=last` 语句,然后你可以修改你的数字

你可以用这个替换你的 for 循环。

inMiddle = false
for line in f:
    sp1 = line.split()
    line = "".join(sp1) + '\n'

    if line == 'Middle':
        inMiddle = true

    if inMiddle and line != 'Last':
        #MODIFY YOUR NUMBERS HERE
    elif line == 'Last':
        inMiddle = false
于 2013-07-12T17:51:09.163 回答
0

基本上,您正在设置一个标志来表示您在“该部分”中。下面我可以选择在完成时设置一个不同的标志。例如,当 flag 为 2 时,您可以退出。

with open('file.txt') as f, open('out.txt', 'w') as f2:

   section = 0;

   for line in f:
      if line.startswith("Middle"):
          section = 1
      elif line.startswith("Last"):
          section = 2



      if section == 1:
        #collect digits and output to other file     
        f2.write(line)         

      elif section == 2:
         #close file and break out
         f.close()
         f2.close()
         break
      else:
          continue
于 2013-07-12T18:04:33.923 回答