doppelte einträge in text datei erkennen und anzeigen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
flambo
User
Beiträge: 10
Registriert: Mittwoch 7. März 2012, 15:05

Hallo zusammen,
Ich bin ein absoluter Python Anfänger und habe allgemein wenig bis keine Programmiererfahrung. Ich möchte ein Script machen, welches mir alle Werte aus einer bestimmten Spalte aus einer Textdatei ausliest und mir alle Doppelten anzeigt. Kann mir jemand Tipps geben wie ich das anstellen soll? Ich habe herausgefunden, wie ich mit dem CSV-Reader die Werte in eine Liste lesen kann, aber dann komme ich nicht wirklich weiter. Mein Code:

Code: Alles auswählen

file_in = open("result.txt","rb")
csvreader1=csv.reader(file_in, delimiter='\t')
double = []

for row in csvreader1:
    double.append(row[2])
Wie kann ich jetzt alle doppelten Werte in der Liste double herausfinden?
Zuletzt geändert von Anonymous am Mittwoch 7. März 2012, 15:53, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Hallo,

bevor es inhaltlich wird: Worin liegt Dein Interesse? Ist das eine Hausaufgabe oder reines Mittel zum Zweck oder willst Du jetzt Python wirklich lernen?

Bitte benutze die Code-Tags, wenn Du Quellcode hier postest. Für Python-Code haben wir sogar spezielle Python-Code-Tags; die bieten noch nettes Syntax-Highlighting. Generell ist das wichtig, da in Python Leerzeichen inhärenter Bestandteil der Syntax sind. Dein Code wäre so gar nicht lauffähig, da die Einrückungen verloren gegangen sind.

Zur Frage: Eine Möglichkeit wäre die Klasse ``Counter`` aus dem ``collections``-Modul zu verwenden:

Code: Alles auswählen

In [20]: foo = (1, 2, 3, 42, 2, 42)

In [21]: from collections import Counter

In [22]: Counter(foo)
Out[22]: Counter({2: 2, 42: 2, 1: 1, 3: 1})
Damit hast Du ein Dictionaty artiges Objekt, welches zu jedem Item die Anzahl gespeichert hat. Dieses kannst Du nun durchgehen und alle Elemente herausfiltern, die eine Anzahl "> 1" haben.

Zuvor musst Du natürlich noch eine Liste (``foo`` ist bei mir ein Tupel!) erstellen, in denen Du die Werte der gewünschten Spalte zusammenfasst. Das kannst Du über einen Indexzugriff sehr einfach realisieren:

Code: Alles auswählen

In [23]: m = ((1, 2), (3, 4), (5, 6))

In [24]: [row[1] for row in m]
Out[24]: [2, 4, 6]

In [25]: [row[0] for row in m]
Out[25]: [1, 3, 5]
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

flambo hat geschrieben:Wie kann ich jetzt alle doppelten Werte in der Liste double herausfinden?
Man könnte mit collections.Counter arbeiten.

Code: Alles auswählen

from collections import Counter

data = [1, 2, 3, 2, 4, 6, 3, 7, 5, 2, 8, 5, 1, 9, 8, 3]

count = Counter(data)
print(count)
for key, value in count.iteritems():
    if value > 1:
        print(key)

# most_common wird für die Aufgabenstellung hier nicht gebraucht, ist aber eine interessante Methode
print(count.most_common(2))
flambo
User
Beiträge: 10
Registriert: Mittwoch 7. März 2012, 15:05

Vielen Dank!!! Mit Collections Counter konnte ich es lösen!!!
flambo
User
Beiträge: 10
Registriert: Mittwoch 7. März 2012, 15:05

]Hallo,

bevor es inhaltlich wird: Worin liegt Dein Interesse? Ist das eine Hausaufgabe oder reines Mittel zum Zweck oder willst Du jetzt Python wirklich lernen?
Ich schreibe ein Script welches MAC-Adressen mit zusatzlichen Informationen aus einer Text-Datei ausliest. Dieses Script soll mir alle MAC-Adressen welche zweimal vorkommen und alle welche dreimal oder mehr vorkommen in eine Liste schreiben.
Bitte benutze die Code-Tags, wenn Du Quellcode hier postest. Für Python-Code haben wir sogar spezielle Python-Code-Tags; die bieten noch nettes Syntax-Highlighting. Generell ist das wichtig, da in Python Leerzeichen inhärenter Bestandteil der Syntax sind. Dein Code wäre so gar nicht lauffähig, da die Einrückungen verloren gegangen sind.

Zur Frage: Eine Möglichkeit wäre die Klasse ``Counter`` aus dem ``collections``-Modul zu verwenden:

Code: Alles auswählen

In [20]: foo = (1, 2, 3, 42, 2, 42)

In [21]: from collections import Counter

In [22]: Counter(foo)
Out[22]: Counter({2: 2, 42: 2, 1: 1, 3: 1})
Damit hast Du ein Dictionaty artiges Objekt, welches zu jedem Item die Anzahl gespeichert hat. Dieses kannst Du nun durchgehen und alle Elemente herausfiltern, die eine Anzahl "> 1" haben.

Zuvor musst Du natürlich noch eine Liste (``foo`` ist bei mir ein Tupel!) erstellen, in denen Du die Werte der gewünschten Spalte zusammenfasst. Das kannst Du über einen Indexzugriff sehr einfach realisieren:

Code: Alles auswählen

In [23]: m = ((1, 2), (3, 4), (5, 6))

In [24]: [row[1] for row in m]
Out[24]: [2, 4, 6]

In [25]: [row[0] for row in m]
Out[25]: [1, 3, 5]
Mein Code sieht jetzt folgendermassen aus:

Code: Alles auswählen

import csv, time, tkMessageBox
from Tkinter import *
from collections import Counter

file_in = open("result.txt","rb")
csvreader1=csv.reader(file_in, delimiter='\t')
csvreader1.next()
csvreader1.next()

doublemac = []
doublemacinf = []
manymacinf = []

for row in csvreader1:
    doublemac.append(row[2])

    count = Counter(doublemac)
    for key, value in count.iteritems():
        if value == 2:
            if (row[2] == (key)) and (row[5] != "trusted2"):
                doublemacinf.append( (row[0],row[1],row[2],row[3],row[4],row[6],row[7]) )          
                print doublemacinf
        if value > 2:
            if (row[2] == (key)) and (row[5] != "trusted3"):
                manymacinf.append( (row[0],row[1],row[2],row[3],row[4],row[6],row[7]) )          
                print manymacinf
        
file_in.close()
Beim ersten if (if value == 2:) möchte ich eigentliche alle MAC-Adressen welche zweimal vorkommen mit den Zusatzinformation in die Liste doublemacinf hinein bringen. Wenn aber eine MAC-Adresse mehr als 2mal vorkommt will ich diese in die Liste manymacinf hinein bringen. Dies geschieht mit dem zweiten if und funktioniert auch. Wenn ich aber drei MAC-Adressen habe welche in row[5] trusted3 haben dann will ich diese in keiner Liste. Das Problem: Es kommte dann doch immer eine MAC-Adresse in die Liste doublemacinf...

OK ich jetzt sehr unverständlich geschrieben, aber vielleicht versteht ihr ja was ich meine...
bb1898
User
Beiträge: 200
Registriert: Mittwoch 12. Juli 2006, 14:28

flambo hat geschrieben: Beim ersten if (if value == 2:) möchte ich eigentliche alle MAC-Adressen welche zweimal vorkommen mit den Zusatzinformation in die Liste doublemacinf hinein bringen. Wenn aber eine MAC-Adresse mehr als 2mal vorkommt will ich diese in die Liste manymacinf hinein bringen. Dies geschieht mit dem zweiten if und funktioniert auch. Wenn ich aber drei MAC-Adressen habe welche in row[5] trusted3 haben dann will ich diese in keiner Liste. Das Problem: Es kommte dann doch immer eine MAC-Adresse in die Liste doublemacinf...
Das liegt daran, dass Du beim Einlesen jeder einzelnen Zeile eine neue Instanz von Counter(doublemac) auf dem aktuellen Stand der Liste doublemac erzeugst und untersuchst. Damit wird eine MAC-Adresse, die insgesamt dreimal vorkommt, beim zweiten Vorkommen in doublemacinf geschrieben, weil sie in diesem Augenblick die Bedingungen dafür erfüllt.

Einerseits ist Counter eigentlich dafür gedacht, auf die komplette Liste angewandt zu werden, wenn sie fertig ist, also nach der Schleife. Und die Information, wie oft ein bestimmter Schlüssel vorkommt, stimmt ja auch erst dann. Andererseits brauchst Du die Zusatzinformationen aus den Mehrfachzeilen, und die wären dann weg. Deshalb würde ich das Ganze von vornherein anders anfangen, ohne Counter:

Ein Dictionary, nennen wir es fullmacinf. Dort hinein kommt jede Zeile beim Lesen; die MAC-Adresse, also row[2] wird der Schlüssel. Für den Wert sehe ich zwei Möglichkeiten:
Wenn eine MAC-Adresse mehrfach vorkommt, genügt dann die Zusatzinformation aus der ersten oder letzten gefundenen Zeile, oder genügt sie nicht? Im Augenblick geht Dir die erste Zusatzinformation allemal verloren, die zweite und ggf. dritte bekommst Du - und eine vierte oder weitere geht wieder verloren.

Wenn Du eigentlich alle zwei, drei oder vielleicht noch mehr Zusatzinformations-Tupel brauchst, dann muss der Wert eine Liste dieser Tupel sein. Mit der Dictionary-Methode fullmacinfo.getdefault() (Details in der Dokumentation) lässt sich das ganz bequem machen. Am Ende gehst Du das Dictionary durch und prüfst jeweils die Länge der Liste. Ist sie 2 bzw. 3, guckst Du noch in die einzelnen Tupel wegen trusted2 bzw. trusted3 und schreibst Deine Tupel in die richtige Liste.

Dieses Verfahren funktioniert auch, wenn Du nicht alle Zusatzinformations-Zeilen brauchst (oder wenn die vielleicht sowieso bei gleichem Schlüssel übereinstimmen). Aber statt dessen könntest Du dann auch als Wert ein Tupel aus einer Zahl und Deiner Zusatzinformation bilden und den Wert jedesmal erhöhen, wenn Du wieder auf den gleichen Schlüssel triffst.
Antworten