2015-06-04 11 views
7

Ich lerne immer noch Python, und ich habe eine Frage, die ich nicht lösen konnte. Ich habe eine sehr lange Zeichenfolge (Millionen von Zeilen lang), die ich gerne in eine kleinere Stringlänge aufteilen würde, basierend auf einer bestimmten Anzahl von Vorkommen eines Delimeters.Python - Aufteilen einer großen Zeichenfolge nach Anzahl der Trennzeichen

Zum Beispiel:

ABCDEF 
// 
GHIJKLMN 
// 
OPQ 
// 
RSTLN 
// 
OPQR 
// 
STUVW 
// 
XYZ 
// 

In diesem Fall würde ich mag auf „//“ aufzuspalten basierte und eine Reihe von allen Zeilen vor dem n-ten Auftreten des delimeter zurückzukehren.

So eine Eingabe von // um 1 die Zeichenfolge Aufspalten zurückkehren würde:

ABCDEF 

eine Eingabe durch // durch 2, um die Zeichenfolge zu spalten zurückkehren würde:

ABCDEF 
// 
GHIJKLMN 

ein Eingang Spaltung der String durch // von 3 zurückkehren würde:

ABCDEF 
// 
GHIJKLMN 
// 
OPQ 

Und so weiter ... jedoch, Die Länge der ursprünglichen 2 Millionen Zeile schien ein Problem zu sein, als ich einfach versuchte, den gesamten String und "//" zu teilen und einfach mit den einzelnen Indizes zu arbeiten. (Ich habe einen Speicherfehler erhalten) Vielleicht kann Python nicht so viele Zeilen in einem Split verarbeiten? Also kann ich das nicht tun.

Ich bin auf der Suche nach einer Möglichkeit, die ich brauche nicht die gesamte Zeichenfolge in hunderttausend Indexen zu teilen, wenn ich nur 100 brauche, sondern nur von Anfang an bis zu einem bestimmten Punkt, zu stoppen und zurückzukehren alles davor, was ich vermute, kann auch schneller sein? Ich hoffe, meine Frage ist so klar wie möglich.

Gibt es einen einfachen oder eleganten Weg, dies zu erreichen? Vielen Dank!

+2

Warum verwenden Sie einen Generator, um die ersten n Elemente zu lesen, bis Sie die erforderliche Anzahl von "//" Trennzeichen lesen? So lesen Sie nur, was Sie brauchen –

+0

Danke, ich werde auch einen Blick in Generatoren werfen, da ich mit ihnen nicht vertraut bin. – Indie

+0

Bitte zeigen Sie, welchen Code Sie bisher ausprobiert haben. –

Antwort

1

Wenn Sie mit Dateien statt Strings im Speicher arbeiten möchten, hier ist eine andere Antwort.

Diese Version ist als eine Funktion geschrieben, die Zeilen liest und sie sofort ausgibt, bis die angegebene Anzahl von Begrenzern gefunden wurde (kein zusätzlicher Speicher zum Speichern der gesamten Zeichenfolge erforderlich).

def file_split(file_name, delimiter, n=1): 
    with open(file_name) as fh: 
     for line in fh: 
      line = line.rstrip() # use .rstrip("\n") to only strip newlines 
      if line == delimiter: 
       n -= 1 
       if n <= 0: 
        return 
      print line 

file_split('data.txt', '//', 3) 

Hiermit können Sie die Ausgabe in eine neue Datei wie folgt schreiben:

python split.py > newfile.txt 

Mit ein wenig zusätzliche Arbeit, können Sie argparse verwenden Parameter an das Programm zu übergeben.

+0

Das funktioniert eigentlich perfekt, und es hat kein Problem, die 2 Millionen Zeile Datei zu behandeln. Vielen Dank! – Indie

0

Zum Beispiel:

i = 0 
    s = "" 
    fd = open("...") 
    for l in fd: 
     if l[:-1] == delimiter: # skip last '\n' 
      i += 1 
     if i >= max_split: 
      break 
     s += l 
    fd.close() 
0

Als effizienter Weise können Sie die Tannen N Linien getrennt von Ihrem Begrenzer lesen kann also, wenn Sie sicher sind, dass alle Ihre Leitungen durch Trennzeichen gespaltet werden Sie itertools.islice verwenden können, zu tun der Auftrag:

from itertools import islice 
with open('filename') as f : 
    lines = islice(f,0,2*N-1) 
0

die Methode, die mir in den Sinn kommt, wenn ich Ihre Frage verwendet eine for-Schleife lesen , wo Sie die Zeichenfolge in mehrere zerschneiden (zum Beispiel die 100 Sie genannt) durch die und iterieren Teilzeichenfolge

Jetzt können Sie durch alle Elemente durchlaufen die ganze 2 Millionen (!) Zeile durchlaufen.

Beste, was hier zu tun ist eigentlich eine rekursive Funktion daraus machen (wenn das, was Sie wollen):

thestring = "" #your string 
steps = 100 #length of the strings you are going to use for iteration 

def iterateThroughHugeString(beginning): 
    substring = thestring[:beginning+steps] #this is the string you will split and iterate through 
    thelist = substring.split("//") 
    for element in thelist: 
     if(element you want): 
      #do your thing with the line 
     else: 
      iterateThroughHugeString(beginning+steps) 
      # and go again from the start only with this offset 
0

Da Sie Python lernen es eine Herausforderung sein würde, eine vollständige dynamische Lösung zu modellieren. Hier ist eine Vorstellung davon, wie Sie ein Modell erstellen können.

Hinweis: Das folgende Code-Snippet funktioniert nur für Dateien, die im angegebenen Format vorliegen (siehe 'For Instance' in der Frage). Daher ist es eine statische Lösung.

num = (int(input("Enter delimiter: ")) * 2) 
with open("./data.txt") as myfile: 
    print ([next(myfile) for x in range(num-1)]) 

Jetzt, wo die Idee haben, können Sie Pattern-Matching und so weiter verwenden.

Verwandte Themen