2016-04-14 5 views
-1

Ich habe ein Problem beim Sortieren einer großen Textdatei. Die Textdatei sieht wie folgt aus:Wie sortiere ich eine Textdatei basierend auf dem String-Wert der letzten Spalte mit Python?

word, two words, 15, 988, anotherword, 99 
also some words, nope, 20, 122, characters, 39 
text, words words, 10, 300, more words, 9 

Das Ende jeder Zeile ein Zeilenende-Zeichen aufweist (\ n).

Ich würde diese Datei absteigend sortieren, basierend auf der Ganzzahl in der letzten Spalte.

habe ich den folgenden Code, den ich hier auf Stackoverflow gefunden:

from operator import itemgetter 

with open ('sourcefile.txt') as fin: 
lines = [line.split(',') for line in fin] 
lines.sort(key=itemgetter(5),reverse=True) 
with open('sortedfile.txt', 'w') as fout: 
    for el in lines: 
     fout.write('{0}\n'.format(','.join(el))) 

Das Problem, das ich bin mit dieser Lösung bekommen, ist, dass das Skript in alphabetischer Reihenfolge ist die Sortierung. Wie so:

word, two words, 15, 988, anotherword, 99 
text, words words, 10, 300, more words, 9 
also some words, nope, 20, 122, characters, 39 

Was könnte eine praktische Lösung für dieses Problem sein?

Antwort

0

Sie sortieren Strings, so dass sie alphabetisch sortiert werden. Wenn Sie numerisch sortieren möchten, achten Sie darauf, ganze Zahlen zu sortieren. Um dies zu tun, stellen Sie sicher, dass das sechste Element in lines ist eigentlich eine ganze Zahl ist, einfach durch Aufruf:

lines[5] = int(lines[5])

bevor Sie sortieren.

0

Der Code mit einigen Optimierungen:

with open ('sourcefile.txt') as fin, open('sortedfile.txt', 'w') as fout: 
    lines_and_numbers = [(line, int(line.rsplit(',', 1)[1])) for line in fin] 
    for el in sorted(lines_and_numbers, key=lambda l:l[1], reverse=True): 
     fout.write(el[0]) 

I eine Liste lines_and_numbers erstellen, die 0 und die ganzzahlige Anzahl von jeweils letzten Spalte der Leitung als Element 1

enthält die ursprüngliche Linie als Element von Tupeln besteht Dann überspringe ich diese Liste, sortiert nach Element 1 jedes Tupels.

So müssen Sie nicht jede Teillinie wieder zusammenfügen und Sie müssen keinen weiteren Zeilenumbruch anhängen, da der alte noch vorhanden ist.

Ich ersetzte auch diese importierte Funktion durch einen einfachen Lambda-Ausdruck.

+0

arbeitete Diese wie ein Zauber. Ich brauchte eine Weile, um zu verstehen, was du getan hast, aber ich denke, ich tue es jetzt! Vielen Dank. –

+0

@DavidDeSmedt Statt "Danke" -Kommentare zu schreiben, akzeptieren Sie die Antwort, indem Sie auf das graue Häkchen-Symbol links davon klicken. Auf der [help] oder der kleinen [tour] Seite erfahren Sie mehr darüber, wie diese Seite funktioniert. –

0

Sie könnten die Zeichenfolge zuerst mit Zeilenumbruch teilen; Sortieren Sie dann die Liste basierend auf der Ganzzahl in der letzten Spalte. [::-1] ist die Liste umkehren, so dass es in absteigender Reihenfolge ist.

import re 
with open('sample.txt', 'r') as fin, open('fout.txt', 'w') as fout: 
    fout.write('\n'.join(sorted(fin.read().split('\n'), key=lambda x: int(re.findall('(\d+)', x)[-1]))[::-1])) 

Ausgabedatei Inhalt:

word, two words, 15, 988, anotherword, 99 
also some words, nope, 20, 122, characters, 39 
text, words words, 10, 300, more words, 9 
Verwandte Themen