Unterliste auf doppelte Einträge Prüfen

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.
LRK
User
Beiträge: 38
Registriert: Sonntag 16. Juni 2019, 21:00

Hallo zusammen,
mein Vorhaben, Ich möchte unterliste durchsuchen/vergleichen um zu überprüfen ob ein Eintrag doppelt vorkommt und mir den Index des doppelten Eintrag ausgeben lassen.

unterliste = [[A,B],[C,D],[E,F],[C,E],[F,C]]

Versuche es nochmal anderst aus zu drücken,
Kommt A,B oder C... in irgend einem anderem Objekt vor?
Wenn Ja!
Welches Object? = A,B oder C etc.... wurde ...
Wie oft? = 3 Mal in...
Wo kommt es vor? = Unterliste[1][0] und unterliste[3][0] und unterliste[4][1] gefunden.
__deets__
User
Beiträge: 14533
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ungetestet:

Code: Alles auswählen

found = set()
res = []
for i, sublist in enumerate(unterliste):
    for j, item in enumerate(sublist):
         if item in found: 
                res.append((I, j))
          found.add(item)
Sirius3
User
Beiträge: 17746
Registriert: Sonntag 21. Oktober 2012, 17:20

@LRK: und was hast Du schon versucht? Welche Gedanken zur Lösung hast Du Dir schon gemacht? Wo kommst Du nicht weiter?
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@LRK: Wie soll das Ergebnis denn aussehen?
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
LRK
User
Beiträge: 38
Registriert: Sonntag 16. Juni 2019, 21:00

@__deets__
Danke, werde es später versuchen.

@Sirius3
Bitte nicht lachen oder schimpfen. ;D

Code: Alles auswählen

e = 0
d = len(test)
f = 0
count = 0
while e <= d:
    for x in test:
	if test[f][1] in x:
	    count = count + 1
	elif count >= 1:
	    with open(my_test2_path,'a') as my_test2:
		my_test2.write(str(test[f][1]) + " : " + str(count) + "\n")
		count = 0
		f = f + 1
	elif count == 1 or count <= 1:
	    count = 0
	    f = f + 1
    e = e +1
@__blackjack__
Wie das Ergebnis ungefähr aussehen soll. Hab ich oben versucht zu beschreiben.

Gesuchtes Object: A B C etc....
Vorkommen: 3 Mal
Position: Unterliste[1][0]; unterliste[3][0]; unterliste[4][1]
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@LRK: Naja, ich meinte nicht in Worten sondern wie soll das Ergebnis ganz konkret aussehen. Wenn Du das für das Beispiel von Hand machen würdest.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
LRK
User
Beiträge: 38
Registriert: Sonntag 16. Juni 2019, 21:00

LRK hat geschrieben: Samstag 10. August 2019, 18:05 @__deets__
Danke, werde es später versuchen.

@Sirius3
Bitte nicht lachen oder schimpfen. ;D
Mein Vorstellung ist so.
Ich nehme das erste Object aus meiner Oberen Liste (unterliste[0]) und dessen unterliste A = (unterliste[0][0]). Lasse dann in der unterliste im ersten Object danach suchen und zähle wie oft es vorkommt. Wenn es 0 mal oder nur 1 mal vorkommt setze ich den Objekt-Zähler wieder auf 0 und gehe in der Oberen-Liste ein Object weiter (unterliste[1]). Wenn es mehr als einmal vorkommt, soll es mir denn Object-Zähler ausgeben, den Index also bsp. (unterliste[3][0]) und das Object das er gesucht hat C. Und dann mit dem nächsten Object in der unterliste suchen (unterliste[0][1]).
In meinem Beispiel wäre das Ergebnis:
Beispiel:
unterliste = [[A,B],[C,D],[E,F],[C,E],[F,C]]
Ergebnis:
"C" kommt 3 mal vor. "C" kommt in "[1][0]","[3][0]","[4][1]" vor.


Code: Alles auswählen

e = 0
d = len(test)
f = 0
count = 0
while e <= d:
    for x in test:
	if test[f][1] in x:
	    count = count + 1
	elif count >= 1:
	    with open(my_test2_path,'a') as my_test2:
		my_test2.write(str(test[f][1]) + " : " + str(count) + "\n")
		count = 0
		f = f + 1
	elif count == 1 or count <= 1:
	    count = 0
	    f = f + 1
    e = e +1
@__blackjack__
Wie das Ergebnis ungefähr aussehen soll. Hab ich oben versucht zu beschreiben.

Gesuchtes Object: A B C etc....
Vorkommen: 3 Mal
Position: Unterliste[1][0]; unterliste[3][0]; unterliste[4][1]
Zuletzt geändert von LRK am Samstag 10. August 2019, 21:09, insgesamt 1-mal geändert.
LRK
User
Beiträge: 38
Registriert: Sonntag 16. Juni 2019, 21:00

Ich würde Blatt 1 in die hand nehmen, nach dem ersten Wort suchen mir Wort,Position und anzahl aufschreiben. Dann das nächste Blatt nehmen nach dem Wort suchen, aufschreiben. Dann das zweite Wort, aufschreiben. Und so weiter bis ich alle Wörter durch habe und alle Blätter. ':)
Oder
"C" kommt 1 mal in "[1][0]" vor.
"C" kommt 1 mal in "[3][0]" vor.
"C" kommt 1 mal in "[4][1]" vor.

"C" kommt 3 mal vor. In "[1][0]","[3][0]","[4][1]"
Sirius3
User
Beiträge: 17746
Registriert: Sonntag 21. Oktober 2012, 17:20

Ein paar Anmerkungen zum Code: eingerückt wird immer mit 4 Leerzeichen pro Ebene, nicht Leerzeichen und Tabs mischen. Dazu kannst Du Deinen Editor richtig einstellen.
Statt der while-Schleife hast Du eigentlich eine for-Schleife. Weil die Schleife sowieso nur dafür sorgen soll, dass alles so oft wie es Elemente in test gibt, wiederholt werden soll (der Sinn sei mal dahingestellt), kann man auch direkt über die Elemente in test iterieren, statt eines Indexes.
Welche Fälle deckt das zweite elif ab, was nicht schon auch durch das erste elif abgedeckt ist?
Das wäre ein Fall für einen else-Block, aber da der Inhalt des Blocks auch im elif davor enthalten ist, ist das ein Fall für eine weitere Schachtelungsebene.
Statt für jeden Eintrag wieder die Datei zu öffnen, macht man das einmal für die gesamte Schleife.
Was rauskommt ist das:

Code: Alles auswählen

f = 0
count = 0
with open(my_test2_path,'a') as output:
    for _ in test:
        for x in test:
            if test[f][1] in x:
                count += 1
            else:
                if count >= 1:
                    output.write(f"{test[f][1]} : {count}\n")
                count = 0
                f += 1
Diese verschachtelten for-Schleifen mit dem `f` als zusätzlichen Zähler ist für mich schwer zu verstehen. Vor allem ist nicht garantiert, dass `f` nicht zu groß wird und es einen IndexError gibt.

Wenn Du vor einem Problem stehst, das zu komplex ist, versuche es in einfachere Unterprobleme zu zerlegen. Erster Schritt wäre hier, ermitteln aller verschiedener Elemente (das geht mit Sets) und zweiter Schritt, für jedes dieser Elemente die Vorkommen zu zählen (das machst Du ja quasi mit Deiner inneren for-Schleife schon).
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Code: Alles auswählen

#!/usr/bin/env python3
from collections import defaultdict


def main():
    data = [['A', 'B'], ['C', 'D'], ['E', 'F'], ['C', 'E'], ['F', 'C']]
    print(data)

    letter2paths = defaultdict(list)
    for i, letters in enumerate(data):
        for j, letter in enumerate(letters):
            letter2paths[letter].append((i, j))
    
    for letter, paths in sorted(letter2paths.items()):
        path_count = len(paths)
        if path_count > 1:
            paths_string = ', '.join(f'[{i}][{j}]' for i, j in paths)
            print(f'{letter!r} kommt {path_count} mal vor: {paths_string}.')


if __name__ == '__main__':
    main()
Ausgabe:

Code: Alles auswählen

[['A', 'B'], ['C', 'D'], ['E', 'F'], ['C', 'E'], ['F', 'C']]
'C' kommt 3 mal vor: [1][0], [3][0], [4][1].
'E' kommt 2 mal vor: [2][0], [3][1].
'F' kommt 2 mal vor: [2][1], [4][0].
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
LRK
User
Beiträge: 38
Registriert: Sonntag 16. Juni 2019, 21:00

Hi, sry das ich paar Tage nicht hier war. Ich war etwas verhindert. Danke für die Hilfe Stellungen.

@Sirius3
Vielen Dank
Ja gebe zu es ist mir wirklich etwas zu komplex manchmal. Dann Versuche ich meist einfach von neuem an zu fangen und alles Stück für Stück durch zu gehen. Meisten hatert es dann schon an den -schleifen und dem zählen.

@__blackjack__
Vielen Dank
Wenn ich dein Script ausführe bekomme ich nen Syntax. Könntest du mir dein Script etwas genauer erläutern. Verstehe da fast nur Bahnhof zb. geschweiften klammern?

paths_string = ', '.join(f'[{i}][{j}]' for i, j in paths)
^
SyntaxError: invalid syntax
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@LRK: Der SyntaxError ist aber nicht 1:1 kopiert, denn das ”caret” (^) zeigt irgendwo ganz weit hinter den Quelltext der Zeile davor.

Kann es sein das Dein Python älter als 3.6 ist? Dann musst Du die f-Zeichenkettenliterale durch normale Zeichenketten ersetzen und die Werte mit der `format()`-Methode hinein formatieren. Von der Methode sollten die geschweiften Klammern eigentlich bekannt vorkommen – das sind die Platzhalter wo die Werte hinein formatiert werden.

Edit:

Code: Alles auswählen

#!/usr/bin/env python3
from collections import defaultdict


def main():
    data = [["A", "B"], ["C", "D"], ["E", "F"], ["C", "E"], ["F", "C"]]
    print(data)

    letter2paths = defaultdict(list)
    for i, letters in enumerate(data):
        for j, letter in enumerate(letters):
            letter2paths[letter].append((i, j))

    for letter, paths in sorted(letter2paths.items()):
        path_count = len(paths)
        if path_count > 1:
            paths_string = ", ".join("[{}][{}]".format(i, j) for i, j in paths)
            print(
                "{!r} kommt {} mal vor: {}.".format(
                    letter, path_count, paths_string
                )
            )


if __name__ == "__main__":
    main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
LRK
User
Beiträge: 38
Registriert: Sonntag 16. Juni 2019, 21:00

@__blackjack__
Habe es soweit hinbekommen danke schön.

paths_string = ', '.join('[' + str(i) + '][' + str(j) + ']' for i, j in paths)

Jetzt möchte ich nur noch die doppelten Einträge, bis auf den ersten aus der Liste entfernen. Aber wie mach ich das. :oops:
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@LRK: Och bitte nicht… `str()` und ``+`` war noch *nie* eine sinnvolle Art Zeichenketten und Werte zusammenzustückeln, selbst vor der `format(()`-Methode nicht.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
LRK
User
Beiträge: 38
Registriert: Sonntag 16. Juni 2019, 21:00

:oops: Tut mir leid. Habe mich bisl im Internet durch tut durch-gekämpft wie ich in einen String umwandeln kann um ihn in eine Datei zu schreiben. :(

Es lag nur an den " Zeichen habe ' drauß gemacht.
LRK
User
Beiträge: 38
Registriert: Sonntag 16. Juni 2019, 21:00

Ich danke dir vielmals habe wieder etwas dazu gelernt.



Jetzt muss ich noch verstehen wie ich die Objekte in der Data Liste, in denen die doppelten Einträge vorkommen, bis auf das jeweilige erste Objekt, aus der Data Liste löschen kann.
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@LRK: Wie? Wo? ' und " sind beides gültige Begrenzer für literale Zeichenketten. Die Zeichenkette die dabei heraus kommt ist gleich:

Code: Alles auswählen

In [94]: 'parrot' == "parrot"
Out[94]: True
Und mit dem schreiben in eine Datei hat das überhaupt nichts zu tun.

Hier ist das herausfiltern von Einträgen die man schon mal gesehen hat ergänzt:

Code: Alles auswählen

#!/usr/bin/env python3
from collections import defaultdict


def main():
    data = [["A", "B"], ["C", "D"], ["E", "F"], ["C", "E"], ["F", "C"]]
    print(data)

    letter2paths = defaultdict(list)
    for i, letters in enumerate(data):
        for j, letter in enumerate(letters):
            letter2paths[letter].append((i, j))

    for letter, paths in sorted(letter2paths.items()):
        path_count = len(paths)
        if path_count > 1:
            paths_string = ", ".join("[{}][{}]".format(i, j) for i, j in paths)
            print(
                "{!r} kommt {} mal vor: {}.".format(
                    letter, path_count, paths_string
                )
            )
    
    seen = set()
    result = list()
    for letters in data:
        filtered_letters = list()
        for letter in letters:
            if letter not in seen:
                seen.add(letter)
                filtered_letters.append(letter)
        result.append(filtered_letters)
    print(result)
    

if __name__ == "__main__":
    main()
Ausgabe:

Code: Alles auswählen

[['A', 'B'], ['C', 'D'], ['E', 'F'], ['C', 'E'], ['F', 'C']]
'C' kommt 3 mal vor: [1][0], [3][0], [4][1].
'E' kommt 2 mal vor: [2][0], [3][1].
'F' kommt 2 mal vor: [2][1], [4][0].
[['A', 'B'], ['C', 'D'], ['E', 'F'], [], []]
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Oder aus der Rubrik „Fun with `glom`“:

Code: Alles auswählen

#!/usr/bin/env python3
from collections import defaultdict
from glom import Flatten, glom, Merge, Path, SKIP


class GetPath:
    @staticmethod
    def glomit(target, scope):
        return (target, scope[Path])


class UnseenOnly:
    def __init__(self):
        self.seen = set()

    def glomit(self, target, _scope):
        if target in self.seen:
            return SKIP
        else:
            self.seen.add(target)
            return target


def target_to_paths():
    def init():
        return defaultdict(list)

    def update(mapping, pair):
        target, path = pair
        mapping[target].append(path)

    return Merge(init=init, op=update)


def format_path(path):
    return "".join(map("[{}]".format, path))


def format_paths(paths):
    return ", ".join(map(format_path, paths))


def print_duplicates(data):
    spec = (
        [[GetPath()]],
        Flatten(init="lazy"),
        target_to_paths(),
        lambda t: sorted((x, ps) for x, ps in t.items() if len(ps) > 1),
    )
    for letter, paths in glom(data, spec):
        print(
            "{!r} kommt {} mal vor: {}.".format(
                letter, len(paths), format_paths(paths)
            )
        )


def main():
    data = [["A", "B"], ["C", "D"], ["E", "F"], ["C", "E"], ["F", "C"]]
    print(data)

    print_duplicates(data)

    filtered_data = glom(data, [[UnseenOnly()]])
    print(filtered_data)


if __name__ == "__main__":
    main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
LRK
User
Beiträge: 38
Registriert: Sonntag 16. Juni 2019, 21:00

Ich muss sagen, ich habe großen Respekt vor dem ganzen und euch\dir und was ihr macht. Es ist für mich sehr schwer alles nach zu vollziehen. Ich glaube das es einfach zu komplex für mich ist. Und Frage mich ob ich je irgendwie Fuß fassen kann im Bereich IT. Ich werde bei Gelegenheit versuchen aus dem ganzen Script schlau zu werden. Ich danke dir vielmals für deine Unterstützung __blackjack__.
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

LRK hat geschrieben: Donnerstag 15. August 2019, 09:16 Ich muss sagen, ich habe großen Respekt vor dem ganzen und euch\dir und was ihr macht. Es ist für mich sehr schwer alles nach zu vollziehen. Ich glaube das es einfach zu komplex für mich ist. Und Frage mich ob ich je irgendwie Fuß fassen kann im Bereich IT.
Lass dich bitte nicht von dem Code, den die anderen dir hier um die Ohren hauen, einschüchtern. Die können dir selber sagen, wie lange sie schon Programmiererfahrung mit und ohne Python haben.
Und solche Codebeispiele schüttelt man nicht als Anfänger aus dem Ärmel. Da stecken viele Jahre Erfahrung dahinter.
Ich bin jetzt seit ca. 1,5 Jahren mit Python unterwegs und selbst ich fühle mich bei manchen Codebeispielen von den "alten Hasen" hier noch immer ziemlich beeindruckt.
Learning by doing und das jeden Tag! Nicht verzagen und die Flinte ins Korn werfen auch wenn du das Gefühl hast, das geht gar nicht alles in deinen Kopf.
Glaube mir, das geht!
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Antworten