Назначение нескольких строк файла нескольким переменным с использованием .readline () в цикле «для строки в данных» - PullRequest
2 голосов
/ 25 марта 2012

Я пытаюсь использовать цикл for line in data:, чтобы присвоить первые 3 строки файла 3 различным переменным (по одной строке для каждой переменной) и сделать так, чтобы он повторялся для каждых 3 строк, чтобы при наличии 9 строкв файле каждая переменная будет содержать 3 разные строки на протяжении итераций, но я не могу понять это вообще.

Пока мой основной код выглядит примерно так:

for line in infile:

  to_line = infile.readline()
  from_line = infile.readline()
  header_line = infile.readline()

Но он просто не работает.Он присваивает каждую другую строку моего файла каждой переменной (то есть 4 строки каждой переменной, а не все строки назначаются).

Суть программы заключается в обработке входного файла, содержащего 9 строк (строка «to», строка «from» и строка «subject» для каждого электронного письма [всего 3 электронных письма]), а затем сортировка ихоснованный на том, являются ли они спамом или "хорошей" почтой.

Придерживающееся условие, которое я имею для этого, заключается в том, что он предназначен для курса в колледже, и мне не разрешено использовать то, что нам еще предстоит пройти в классе (у нас 8 недель, поэтому у нас естьнебольшая база знаний базовой информации для использования).Если кто-нибудь ответит чем-то, что я не могу использовать, я сообщу вам.

Ответы [ 5 ]

10 голосов
/ 25 марта 2012

На самом деле вам не нужно вызывать readline, достаточно просто перебрать файл. Вы можете использовать функцию zip для перегруппировки линий. Таким образом, общее решение будет выглядеть как

for odd_line,even_line in zip(infile, infile):
     # Do something

Если вы хотите сначала создать список всех четных и нечетных строк (и это редко бывает хорошей структурой данных), вы можете просто добавить список, например, так:

odd_lines = []
even_lines = []
for odd_line,even_line in zip(infile, infile):
     odd_lines.append(odd_line)
     even_lines.append(even_line)

В качестве альтернативы используйте

lines = list(infile)

, чтобы получить список всех строк, а затем ломтиками , чтобы извлечь часть файла. Например,

even_lines = lines[1::2]

Другой альтернативой является использование итератора с циклом while. Просто позвоните next несколько раз. Например, это печатает все нечетные строки:

iterator = iter(infile)
while True:
  try:
    odd_line = next(iterator)
    print(odd_line)
    even_line = next(iterator)
  except StopIteration:
    break

Если вы не хотите использовать break (а это crazy ), вы можете просто перехватить исключение вне цикла:

iterator = iter(infile)
try:
  while True:
    odd_line = next(iterator)
    print(odd_line)
    even_line = next(iterator)
except StopIteration:
  pass # end of file reached

Вместо использования итератора вы также можете использовать readline:

odd_lines = []
even_lines = []
while True:
  line = infile.readline()
  if not line: # End of file reached
    break
  odd_lines.append(line)

  line = infile.readline()
  if not line: # End of file reached
    break
  even_lines.append(line)

Опять же, если вы действительно не можете использовать break заявления, вы можете подделать их:

odd_lines = []
even_lines = []
go_on = True
while go_on:
  line = infile.readline()
  if even_line:
    odd_lines.append(line)
    line = infile.readline()
    if line:
      even_lines.append(line)
    else:
      go_on = False
5 голосов
/ 25 марта 2012

Поскольку файлы являются итераторами, их можно объединять в группы. Это означает, что ответом на ваш вопрос является очень простой фрагмент кода:

with open(filename) as f:
    for to_line, from_line, header_line in zip(f, f, f):
        print (to_line, from_line, header_line)

Для студентов, которым запрещено использовать zip , также будет работать следующее:

f = open(filename)
try:
    while True:
        to_line, from_line, header_line = next(f), next(f), next(f)
        print (to_line, from_line, header_line)
except StopIteration:
    pass
finally:
    f.close()
4 голосов
/ 25 марта 2012

Это не работает, потому что начало цикла (т. Е. for line in infile:) читает следующую строку из infile, которую вы в основном выбрасываете, не используя ее.Альтернативой этому может быть чтение всех строк заранее в список, а затем работа по списку:

# read all lines from the file into a list, where each list element is one line
lines = infile.readlines()

# iterate through the list three lines at a time, until you run out of lines
line_number = 0
while line_number < len(lines):
    to_line = lines[line_number]
    from_line = lines[line_number+1]
    header_line = lines[line_number+2]
    line_number += 3
1 голос
/ 25 марта 2012

Каждая итерация цикла for читает строку из infile в line. Попробуйте этот код:

for line in infile:
    print line

Это читает каждую строку infile в line и печатает каждую line.

Итак, когда вы делаете infile.readline() внутри цикла, вы фактически читаете другую строку, поскольку первая была прочитана в line.

Легко запутаться, когда вы читаете for line in infile по-английски, поскольку вы не понимаете, что это на самом деле означает: «Прочитайте строку из infile в line и выполните приведенный ниже код. больше нет строк для чтения. "

Поскольку вы читаете только 3 строки за раз, вы можете сделать что-то вроде:

infile = open("yourfilename.txt")
for i in range(3):
   to_line = infile.readline()
   from_line = infile.readline()
   header_line = infile.readline()
   # Do something with the lines you just read

Этот цикл будет выполнен 3 раза (см. range(3)), каждый раз читая 3 строки в соответствующие переменные.

0 голосов
/ 25 марта 2012

Это отличное использование для словаря списков. Благодаря этому вы можете получить общее решение, которое будет возвращать словарь каждого индекса номера строки.

Сначала сгенерируйте несколько строк:

with open('/tmp/lines.txt','w') as fw:
    for line in range(10):     # 0 - 9!!!
        print >>fw, 'This is line',line

Теперь прочитайте эти строки в структуру данных, в которой каждая n th строка проиндексирована:

n=3        
with open('/tmp/lines.txt','r') as fr:
    i=0
    ells={i:[] for i in range(n)}
    for line in fr:
        ells[i%n].append(line.strip())
        i+=1

print ells
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...