halloICKEbins
Anmeldungsdatum: 12. September 2017
Beiträge: 226
|
Mahlzeit, habe mal wieder das nachfolgende Problem... ich möchte meine Datei mit dem nachfolgenden Schema sortieren und zwar zuerst die 4 Spalte - reverse und dannach Spalte 1-3 "normal" IP1 IP2 COUNT1 COUNT2
... Ich würde sorted benutzen aber wie kann ich ihm die Spalten sagen? | f = open(output,'w')
lines = open(input, 'r').readlines()
lines_set = set(lines)
for line in sorted(lines_set, reverse = True):
line = line.rstrip()
print(line, file = f)
f.close()
|
|
Marc_BlackJack_Rintsch
Ehemalige
Anmeldungsdatum: 16. Juni 2006
Beiträge: 4702
Wohnort: Berlin
|
@halloICKEbins: Das kann man über das key -Argument regeln und dort eine Funktion übergeben die beispielsweise so aussieht: lambda row: (-row[3], row[:3]) . Wobei das jetzt davon ausgeht da bei row[3] eine Zahl steht, die mit - negiert werden kann. Das reverse=True muss dann natürlich raus.
|
halloICKEbins
(Themenstarter)
Anmeldungsdatum: 12. September 2017
Beiträge: 226
|
Mit for line in sorted(lines_set,key=lambda row: (-row[3], row[:3])): bekomme ich immer Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "<stdin>", line 2, in <lambda>
TypeError: bad operand type for unary -: 'str'
|
Marc_BlackJack_Rintsch
Ehemalige
Anmeldungsdatum: 16. Juni 2006
Beiträge: 4702
Wohnort: Berlin
|
Um noch mal aus meinem letzten Beitrag zu zitieren: „Wobei das jetzt davon ausgeht da bei row[3] eine Zahl steht, die mit - negiert werden kann.“. Es muss halt schon eine Zahl sein. Und da Du die mit „COUNT“ beschrieben hattest, ging ich halt davon aus, dass es eine Zahl ist. Und ich hatte das auch extra erwähnt weil das in Deinem gezeigten Code als Zeichenkette eingelesen wird. Das andere „COUNT“ muss auch umgewandelt werden, wenn es als Zahl sortiert werden soll. Wobei ich gerade sehe, das in dem Code auch überhaupt keine Zeilen in Spalten aufgetrennt werden, was Du ja auch noch machen musst.
|
halloICKEbins
(Themenstarter)
Anmeldungsdatum: 12. September 2017
Beiträge: 226
|
COUNT1 und COUNT2 sind nur Zahlen...aber der Fehler liegt wahrscheinlich in der Aufspaltung.
Ich hätte gedacht, dass lambda row: (-row[3], row[:3]) die Zeilen automatisch aufspaltet und ich dann nur die line ausgeben muss!?
|
Marc_BlackJack_Rintsch
Ehemalige
Anmeldungsdatum: 16. Juni 2006
Beiträge: 4702
Wohnort: Berlin
|
@halloICKEbins: Wieso sollte das die Zeile aufspalten und vor allem wie? Das ist Python und nicht AWK. Du musst die Zeilen aufspalten und die Werte die anders als lexikographisch sortiert werden sollen auch in die entsprechenden Datentypen umwandeln.
|
halloICKEbins
(Themenstarter)
Anmeldungsdatum: 12. September 2017
Beiträge: 226
|
Habe es jetzt wie folgt gelöst: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | def sortier_helfer(item):
z = item[3]
z2 = item[0]
z3 = item[1]
z4 = item[2]
return (-int(z), z2, z3, z4)
with open(inputfile) as fin:
mylist = [[item for item in line.strip().split(' ')] for line in fin]
mylist.sort(key=sortier_helfer)
f = open(outputfile,'w')
for line in mylist:
print(' '.join(map(str, line)), file = f)
f.close()
|
Für Anmerkungen bin ich trotzdem empfänglich und dankbar!
|
Marc_BlackJack_Rintsch
Ehemalige
Anmeldungsdatum: 16. Juni 2006
Beiträge: 4702
Wohnort: Berlin
|
@halloICKEbins: Laut Beschreibung hast Du ja zwei COUNT-Spalten. Die andere musst Du zum sortieren auch in eine Zahl wandeln wenn die Sortierung da auch numerisch sein soll. Sonst kommt beispielsweise die 10 vor der 2. Das map(str, line) ist überflüssig weil das schon alles Zeichenketten sind. mylist ist kein schöner Name und line ist in der zweiten Schleife falsch. rows und row wären besser und üblicher.
Warum wird einmal with mit open() verwendet, beim zweiten mal dann aber nicht?
|
halloICKEbins
(Themenstarter)
Anmeldungsdatum: 12. September 2017
Beiträge: 226
|
Liegt an den verschiedenen Codesnipseln ☹ ... muss ich noch einheitlich schreiben. Das mit COUNT1 konnte ich noch nicht ganz lösen, da ich festgestellt habe, dass dort auch Wörter vorkommen können ... Mir ist schon aufgefallen, dass er es nicht richtig sortiert aber für den ersten Moment ging es so ... bis jetzt habe ich auch noch keine Lösung dafür.
|
Marc_BlackJack_Rintsch
Ehemalige
Anmeldungsdatum: 16. Juni 2006
Beiträge: 4702
Wohnort: Berlin
|
Ungetestet:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 | #!/usr/bin/env python
# coding: utf-8
from __future__ import absolute_import, division, print_function
from functools import total_ordering
DELIMITER = ' '
@total_ordering
class ReverseOrder(object):
def __init__(self, value):
self.value = value
def __eq__(self, other):
return self.value == other.value
def __lt__(self, other):
return other.value < self.value
def convert_count(string):
try:
count = int(string)
except ValueError:
return (float('inf'), string)
else:
return (count, '')
def create_key(row):
return (
ReverseOrder(convert_count(row[3])),
row[0],
row[1],
convert_count(row[2]),
)
def main():
with open('test.txt') as in_file:
rows = sorted(
(line.strip().split(DELIMITER) for line in in_file), key=create_key
)
with open('test2.txt', 'w') as out_file:
out_file.writelines(DELIMITER.join(row) + '\n' for row in rows)
if __name__ == '__main__':
main()
|
convert_count() ist so gestaltet, dass Zeichenketten nach Zahlen sortiert werden. Wenn das umgekehrt sein soll, müsste man in dem Tupel mit den Zeichenketten -∞ verwenden.
|
halloICKEbins
(Themenstarter)
Anmeldungsdatum: 12. September 2017
Beiträge: 226
|
Funktioniert vorzüglich .. Danke
|