2016-04-04 4 views
1

Ich versuche, eine CSV-Datei zu sortieren, die wie folgt aussieht:Wie sortiere ich diese CSV-Datei?

filename,field1,field2 
10_somefile,0,0 
1_somefile,0,0 
2_somefile,0,0 
3_somefile,0,0 
4_somefile,0,0 
5_somefile,0,0 
6_somefile,0,0 
7_somefile,0,0 
8_somefile,0,0 
9_somefile,0,0 

I-Code von einem anderen Thread verwiesen habe:

with open(outfname, "rb") as unsorted_file: 
    csv_f = csv.reader(unsorted_file) 
    header = next(csv_f, None) 
    sorted_data = sorted(csv_f, key=operator.itemgetter(0)) 

with open(outfname, 'wb') as sorted_file: 
    csv_f = csv.writer(sorted_file, quoting=csv.QUOTE_ALL) 
    if header: 
     csv_f.writerow(header) 
    csv_f.writerows(sorted_data) 

Dies wird jedoch die '10_somefile' nicht bewegen bis zum Ende. Wie kann ich das so sortieren, dass es die Nummer vor dem Unterstrich als Sortierfeld verwendet?

+0

Ist das Format immer „X_somefile ....“ oder der „somefile“ Teil der Daten kann auch in der gleichen Reihenfolge ändern ? Wie "1_filea ...", "1_fileb ..". Wenn Letzteres, sollte die korrekte Ausgabe "1_filea, 2_filea, 1_fileb, ...." oder "1_filea, 1_fileb, 2_filea, ..." sein. Dies zeigt an, ob Sie nur nach den Ganzzahlen oder den restlichen Teilen der Zeichenfolge sortieren müssen. –

Antwort

1

Dies geschieht, weil "10" < "1_". Sie möchten ganze Zahlen und keine Zeichenfolgen vergleichen. Dieses Verhalten kann erreicht werden, indem für jede Zeile eine Ganzzahl mit den Zeichen bis zum Unterstrich erstellt wird. Angenommen, Sie können eine Zeichenfolge s (die mit dem itemgetter durchgeführt werden kann, wie Sie gerade tun) erhalten. Dann wird das folgende Lambda (wenn es als key für sorted übergeben wird) tun, was Sie wollen.

key=lambda s: int(s[: (s.index('_'))]))) 

Was diese Funktion tut, ist einfach: Es gibt nur die ganze Zahl aus den Zeichen von s bis zu machte, aber nicht einschließlich, den ersten Unterstrich.

+0

Ich habe das auch versucht und ich bekomme den Fehler: '_' ist nicht in der Liste. Ich vermute, dass dies auf das Format zurückzuführen ist, in dem sich meine Liste befindet: [['10_somefile', '0', '0'], ['1_somefile', '0,' 0 '], ...]. – Colin

+0

@Colin du machst es nur am falschen Ort. 's' in meinem Snippet sollte eine Zeichenfolge sein, keine Liste. Sie können Strings in Python zerlegen. Sowohl .index() als auch [] sollen in einer Zeichenkette ausgeführt werden. Wie Sie in Ihrer Fehlermeldung erfahren, führen Sie sie stattdessen in einer Liste aus. –

1

Unter der Annahme, dass alle Ihre filename Felder mit einer Zahl beginnen, die einfachste, was man tun kann, ist durch die ganze Zahl zu sortieren, indem sie aus dem Dateinamen Parsen.

# Assume this is the data of the CSV after reading it in 
filenames = ['10_somefile,0,0', 
'1_somefile,0,0', 
'2_somefile,0,0', 
'3_somefile,0,0', 
'4_somefile,0,0', 
'5_somefile,0,0', 
'6_somefile,0,0', 
'7_somefile,0,0', 
'8_somefile,0,0', 
'9_somefile,0,0'] 

# Here, we treat the first part of the filename (the number before the underscore) as the sort key. 
sorted_data = sorted(filenames, key=lambda l: (int(l.partition('_')[0]))) 

Wenn Sie Ausgabe sorted_data, es sollte wie folgt aussehen:

['1_somefile,0,0', '2_somefile,0,0', '3_somefile,0,0', 
'4_somefile,0,0', '5_somefile,0,0', '6_somefile,0,0', 
'7_somefile,0,0', '8_somefile,0,0', '9_somefile,0,0', '10_somefile,0,0'] 
+0

Ich kann nicht scheinen, das zu funktionieren und immer den Fehler zu bekommen 'list object hat kein Attribut' partition '. Muß ich meine CSV-Datei zuerst in eine Liste einlesen? Wenn ich das mache, sieht es nicht ganz so aus wie oben: [['10_somefile', '0', '0'], ['1_somefile', '0,' 0 '], ...] – Colin