4 Stimmen

Zwei Dateien gleichzeitig in Python verarbeiten

Ich habe Informationen über 12340 Autos. Diese Informationen sind nacheinander in zwei verschiedenen Dateien gespeichert:

  1. car_names.txt, die eine Zeile für den Namen jedes Fahrzeugs enthält
  2. car_descriptions.txt, die die Beschreibungen der einzelnen Fahrzeuge enthält. Also 40 Zeilen für jedes Auto, wobei die 6. Zeile @CAR_NAME lautet

Ich möchte in Python: für jedes Auto in der Datei car_descriptions.txt den Namen jedes Autos (der aus der anderen Datei stammt) in der 7. Zeile (sie ist leer) hinzufügen, direkt nach @CAR_NAME

Ich dachte darüber nach:

1) 1. Datei lesen und Fahrzeugnamen in einer Matrix/Liste speichern 2) beginne mit dem Lesen der 2. Datei und schreibe jedes Mal, wenn die Zeichenkette @CAR_NAME gefunden wird, einfach den Namen in die nächste Zeile

Aber ich frage mich, ob es einen schnelleren Ansatz gibt, so dass das Programm jedes Mal eine Zeile aus jeder Datei liest und die Änderung vornimmt.

Danke

1 Stimmen

Die 6., 46., 86. usw. Zeile in der zweiten Datei enthält das Literal @CAR_NAME ?

3 Stimmen

Ist Geschwindigkeit wirklich wichtig? Ich kann mit Python 400.000 Zeilen reinen Text in deutlich unter einer Sekunde lesen. Wie viel schneller brauchen Sie?

9voto

Robert Rossney Punkte 91100

Erstellen Sie zunächst einen Generator, der den Fahrzeugnamen aus einer Sequenz abruft. Sie könnten jede 7. Zeile ausgeben; ich habe meinen Generator so eingestellt, dass er jede Zeile ausgibt, die auf die Zeile folgt, die mit @CAR_NAME :

def car_names(seq):
    yieldnext=False
    for line in seq:
        if yieldnext: yield line
        yieldnext = line.startswith('@CAR_NAME')

Jetzt können Sie itertools.izip um beide Sequenzen parallel zu durchlaufen:

from itertools import izip
with open(r'c:\temp\cars.txt') as f1:
    with open(r'c:\temp\car_names.txt') as f2:
        for (c1, c2) in izip(f1, car_names(f2)):
            print c1, c2

1 Stimmen

Wer hat Ihnen gesagt, dass dies Windows ist?

19 Stimmen

Ich teste den von mir eingestellten Code. Wenn es Sie stört, dass mein Rechner unter Windows läuft, empfehle ich Ihnen, sich in einen ruhigen, abgedunkelten Raum zu legen und sich einen kühlen, feuchten Waschlappen über die Augen zu halten, bis das Gefühl vorbei ist.

2 Stimmen

Wow, was für eine hitzige Antwort auf meine Frage! Es sieht so aus, als bräuchten Sie den kühlen Waschlappen mehr als ich! Wie auch immer, mein Kommentar war nur als traurige Anmerkung gemeint: Windows-Benutzer neigen oft dazu, zu denken, dass jeder ein Windows-Benutzer ist. Sie können Ihr Skript mit einer Datei im gleichen Verzeichnis testen (wie dieser andere Typ stackoverflow.com/questions/1731102/ ), oder Sie hätten den Pfad einfach abstrahieren können mit filename . Verbessern Sie Ihre Antwort, anstatt zu schimpfen!

8voto

eduffy Punkte 37562

Ich bin mir nicht sicher, ob ich ganz verstehe, was Sie zu tun versuchen, ist etwas wie dies?

f1 = open ('car_names.txt')
f2 = open ('car_descriptions.txt')
for car_name in f1.readlines ():
        for i in range (6):   # echo the first 6 lines
                print f2.readline ()
        assert f2.readline() == '@CAR_NAME'  # skip the 7th, but assert that it is @CAR_NAME
        print car_name    # print the real car name
        for i in range (33):  # print the remaining 33 of the original 40
               print f2.readline ()

4voto

Alex Martelli Punkte 805329

Lesen car_names.txt spart zwar eine winzige Menge an Speicherplatz (nach heutigen Maßstäben wirklich winzig;-), ist aber auf keinen Fall schneller als das Schlürfen in einem Zug (im besten Fall ist es genau gleich schnell, wahrscheinlich sogar etwas langsamer, es sei denn, das zugrunde liegende Betriebssystem und das Speichersystem leisten großartige Arbeit bei der Zwischenspeicherung/Pufferung von Lesevorschau). Ich schlage also vor:

import fileinput

carnames = open('car_names.txt').readlines()
carnamit = iter(carnames)

skip = False
for line in fileinput.input(['car_descriptions.txt'], True, '.bak'):
  if not skip:
    print line,
  if '@CAR_NAME' in line:
    print next(carnamit),
    skip = True
  else:
    skip = False

Messen Sie also die Geschwindigkeit, mit der dies geschieht, und eine Alternative, die

carnamit = open('car_names.txt')

am Anfang, anstatt alle Zeilen über eine Liste zu lesen, wie meine erste Version -- ich wette, dass die erste Version (sofern es einen messbaren und wiederholbaren Unterschied gibt) sich als schneller erweisen wird.

Übrigens ist das Fileinput-Modul der Standardbibliothek dokumentiert これ und es ist wirklich eine bequeme Möglichkeit, Textdateien "virtuell an Ort und Stelle neu zu schreiben" (wobei die alte Version normalerweise als Backup für den Fall der Fälle aufbewahrt wird - aber selbst wenn der Rechner mitten in der Operation abstürzt, ist die alte Version der Daten noch vorhanden, so dass das "Neuschreiben" in gewissem Sinne atomar in Bezug auf Rechnerabstürze funktioniert, eine nette Kleinigkeit;-).

0 Stimmen

Hallo, entschuldigen Sie, ich verstehe Ihren Ansatz, aber ich bekomme den Fehler: NameError: name 'Next' is not defined am i missing some other library?

0 Stimmen

Ich glaube, das ist neu in Python 2.6. Arbeiten Sie mit einer früheren Version?

0 Stimmen

In 2.5 oder früher benötigen Sie carnamit.next() statt der schöneren next(carnamit) die in 2.6 und höher funktioniert.

1voto

Corey Porter Punkte 1301
for line1, line2 in zip(file(filename1), file(filename2)):
    # do your thing

oder ähnlich

1 Stimmen

Es verschachtelt die Elemente aus einer Liste von Iterables. Als Alternative können Sie itertools.izip verwenden.

0 Stimmen

In diesem speziellen Fall wird eine Liste von Tupeln zurückgegeben, wobei jedes Tupel (Zeile x aus Datei1, Zeile x aus Datei2) ist

4 Stimmen

Aber wie hilft dies überhaupt mit dem Problem des Auftraggebers, 40 Zeilen aus Datei 2 für jede Zeile aus Datei 1 zu verarbeiten?!

0voto

bua Punkte 4611

12340 sind keine Daten (in dem Sinne, dass es auf dem Markt viel größere Daten zu verarbeiten gibt).

Ein noch besserer Ansatz wäre die Verwendung des eingebauten Sqlite-Moduls. Wenn nicht, verwenden Sie ein einfaches Format wie z.B. CSV. Dies ist eine organisierte Struktur. Wenn nicht verwenden Threads, könnten Sie zwei Dateien gleichzeitig verarbeiten.

0 Stimmen

Kann das sqlite-Modul von Python aus verwendet werden? wie?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X