2 votes

Affectation de plusieurs lignes d'un fichier à plusieurs variables à l'aide de .readline() while dans une boucle "for line in data".

J'essaie d'utiliser un for line in data: une boucle pour assigner les 3 premières lignes d'un fichier à 3 variables différentes (une ligne pour chaque variable) et la faire itérer pour chaque 3 lignes, de sorte que s'il y avait 9 lignes dans le fichier, chaque variable contiendrait 3 lignes différentes tout au long des itérations, mais je n'y arrive pas du tout.

Jusqu'à présent, mon code de base ressemble à quelque chose comme ceci :

for line in infile:

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

Mais ça ne marche tout simplement pas. Il affecte une ligne sur deux de mon fichier à chaque variable (c'est-à-dire 4 lignes à chaque variable et toutes les lignes ne sont pas affectées).

Le principe du programme est de traiter un fichier d'entrée contenant 9 lignes (une ligne "to", une ligne "from" et une ligne "subject" pour chaque email [3 emails au total]) et de les trier selon qu'il s'agit ou non de spam ou de "bon" courrier.

Une stipulation importante que j'ai pour ceci est que c'est pour un cours universitaire et je ne suis pas autorisé à utiliser quoi que ce soit que nous n'avons pas encore vu en classe (nous en sommes à 8 semaines donc nous avons une petite base de connaissances d'informations de base à utiliser). Si quelqu'un me répond en me disant qu'il y a quelque chose que je ne peux pas utiliser, je vous le ferai savoir.

10voto

phihag Points 89765

Vous n'avez pas besoin d'appeler readline il suffit d'itérer sur le fichier. Vous pouvez utiliser la fonction zip pour regrouper les lignes. Par conséquent, la solution générique serait la suivante

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

Si vous voulez d'abord créer une liste de toutes les lignes paires et impaires (et c'est rarement une bonne structure de données), vous pouvez simplement ajouter à une liste, comme ceci :

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

Vous pouvez également utiliser

lines = list(infile)

pour obtenir une liste de toutes les lignes, et ensuite tranches pour extraire une partie du fichier. Par exemple,

even_lines = lines[1::2]

Une autre alternative est d'utiliser un itérateur avec une fonction while boucle. Il suffit d'appeler next plusieurs fois. Par exemple, ceci imprime toutes les lignes impaires :

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

Si vous ne voulez pas utiliser break (et c'est fou ), vous pouvez simplement attraper l'exception en dehors de la boucle :

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

Au lieu d'utiliser un itérateur, vous pouvez aussi utiliser 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)

Encore une fois, si vous ne pouvez vraiment pas utiliser break les déclarations, vous pouvez les falsifier :

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

5voto

Raymond Hettinger Points 231

Comme les fichiers sont des itérateurs, ils peuvent être regroupés en groupes. Cela signifie que la réponse à votre question est un morceau de code très simple :

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

Pour les étudiants qui ne sont pas autorisés à utiliser zip le texte suivant fonctionnerait également :

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()

3voto

Brendan Wood Points 2481

Cela ne fonctionne pas car le début de la boucle (c'est-à-dire, for line in infile: ) lit la ligne suivante à partir de infile que vous jetez essentiellement en ne l'utilisant pas. Une alternative à cela serait de lire toutes les lignes en premier lieu dans une liste, puis de travailler à travers la liste :

# 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

1voto

Mig Points 435

Chaque itération de la boucle for lit une ligne de infile en line . Essayez ce code :

for line in infile:
    print line

Cela lit chaque ligne de infile en line et imprime chaque line .

Donc, quand vous faites infile.readline() dans la boucle, vous lisez en fait une autre ligne, puisque la première a été lue dans le fichier line .

C'est facile de s'embrouiller quand on lit for line in infile en anglais, puisque vous ne réalisez pas que cela signifie en fait : "Lire une ligne de infile en line et exécutez le code ci-dessous. Répétez l'opération jusqu'à ce qu'il n'y ait plus de lignes à lire."

Puisque vous ne lisez que 3 lignes à la fois, vous pourriez faire quelque chose comme :

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

Cette boucle sera exécutée 3 fois (voir range(3) ), en lisant chaque fois 3 lignes dans les variables appropriées.

0voto

the wolf Points 10164

C'est une excellente utilisation d'un dictionnaire de listes. Avec cela, vous pouvez avoir une solution générale qui retournera un dictionnaire de chaque index de numéro de ligne.

Tout d'abord, générez quelques lignes :

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

Maintenant, lisez ces lignes dans une structure de données qui a chaque n th ligne indexée :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X