enumerate von Listen - doppelte Einträge

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.
nick21
User
Beiträge: 11
Registriert: Freitag 23. März 2018, 09:28

Guten Morgen zusammen,

Ich habe eine Liste list_a =[ a, b, c, d, e, f, a, b, x, y] und hätte diese gerne mit Zahlen versehen. Dies funktioniert ja soweit über die enumerate Funktion. Allerdings hätte ich gerne doppelte Einträge auch mit der gleichen Zahl versehen list_b = [1, 2, 3, 4, 5, 6, 1, 2, 7, 8]. Kennt da jemand eine Möglichkeit?

Schonmal Danke vorab.

Nick
__deets__
User
Beiträge: 14536
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das wirst du dir programmieren müssen. Zb indem du dein eigenes enumerate schreibst, in Form eines Generators, der sich merkt, was er schon gesehen hat:

Code: Alles auswählen

def enumerate_unique(iterable):
      count = 0 
      seen = set()
      for item in iterable:
          # Magie
          yield count, item
Ein bisschen was musst du noch selbst tun.
nick21
User
Beiträge: 11
Registriert: Freitag 23. März 2018, 09:28

Danke für die schnelle Antwort. Dann setze ich mich mal dran
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@__deets__: ein Set führt auf die falsche Spur.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1020
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Ein set ist genau die passende Datenstruktur für sowas.
Der lookup ist schnell und es gibt keine doppelten Elemente in einem set.

# Magie muss natürlich noch durch den OP ergänzt werden.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
__deets__
User
Beiträge: 14536
Registriert: Mittwoch 14. Oktober 2015, 14:29

Sirius3 hat geschrieben:@__deets__: ein Set führt auf die falsche Spur.
Stimmt. Zu früh am Tag... muss natürlich ein dict sein!
nick21
User
Beiträge: 11
Registriert: Freitag 23. März 2018, 09:28

ich komme nicht auf den richtigen Ansatz, habe dafür wohl auch leider zu wenig Ahnung von der Materie.
Ein Generator erzeugt in meinem Fall die entsprechende Nummer zu dem Eintrag, ohne diese dauerhaft zu speichern. Anschließend was? Anschließend müsste ja die Liste durchsucht werden, ob der Eintrag nochmals vorhanden ist. Falls ja, wird diesem Eintrag die gleiche Nummer zugewiesen.
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@nick21: Du gehst alle Listeneinträge nacheinander durch und merkst Dir zu jedem Eintrag in einem Wörterbuch dessen Nummer. Ist ein Eintrag schon im Wörterbuch, gibst Du ihm die selbe Nummer.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1020
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Oh man, ich bin offensichtlich noch im Tiefschlaf. Natürlich wäre ein dict die einzig richtige Datenstruktur.
Die Idee ist einfach. Als Key wird das jeweilige Objekt aus der Liste und als Value wird der aktuelle Zählerstand verwendet.
Wenn das Objekt bereits im dict als Key vorhanden ist, wird der Wert abgerufen.
Anstatt enumerate musst du etwas anderes verwenden, da ansonsten der Zähler bei jeder Iteration weiter läuft.


EDIT: Ich hab mein Beispiel wieder entfernt. Versuche erstmal den Code umzusetzen.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
nick21
User
Beiträge: 11
Registriert: Freitag 23. März 2018, 09:28

Es wird die Liste mit den Einträgen durchsucht. Bei jedem Eintrag wird überprüft, ob sich dieser bereits in dem dict befindet. Falls ja, soll er den Value ( Nummer ) herausgeben. Wie schreibe ich den anschließend zu dem Listeneintrag?
Falls nicht, soll ein neuer Eintrag im dict erstellt werden mit key=Listeneintrag, value = neue Nummer ( n=n+1 )

Code: Alles auswählen

def enumerate_unique(iterable):
	count = 0 
	seen = dict()
	for item in iterable:
		if item in seen:
			get(item)	# gibt Value ( Nummer) zum entsprechenden Listeneintrag			
						# schreibe value zu key Listeintrag bekommt Nummer 1
		else:	
			n=n+1			# wenn Listeintrag nicht vorhanden, erzeuge Nummer 2	
			seen[item] = n 	# Listeintrag wird neu hinzugefügt mit Nummer 2
			
		yield count, item
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@nick21: wenn Du Deine Funktion einmal aufgerufen hättest, hättest Du merken müssen, dass n nicht definiert ist. Ein `get` irgendwo hinzuschreiben wird auch nicht funktionieren, weil `get` nicht definiert ist. Wie man werte aus einem Wörterbuch liest, sollte gleich neben dem Schreiben in ein Wörterbuch im Tutorial stehen. Und mit den Ergebnis sollte man dann irgendwas machen. Ansonsten ist das doch schon der richtige Weg.
nick21
User
Beiträge: 11
Registriert: Freitag 23. März 2018, 09:28

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: ascii -*-

item = ["a","b","a","c","b","a"]
print item
i=1
print item[i]

def enumerate_unique(iterable):
   count = 0 
   seen = dict()
   n=1
   for item in iterable:
      if item in seen:
         dict.get(item)   # gibt Value ( Nummer) zum entsprechenden Listeneintrag         
                            # schreibe value zu key Listeintrag bekommt Nummer 1
      else: 
        n=n+1            # wenn Listeintrag nicht vorhanden, erzeuge Nummer 2   
        dict[item] = n   # Listeintrag wird neu hinzugefuegt mit Nummer 2
        yield count, item
        print n
#print "Value : %s" % dict.values()
Ich habe meine Liste der Werte. Muss ich darum noch eine for Schleife bauen, die die Werte einzelnd ausliest?
__deets__
User
Beiträge: 14536
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du musst schon fuer beide Faelle ein yield machen. Und den Wert, den du nachschlaegst natuerlich auch benutzen, statt nix zu tun. Und du musst count natuerlich auch erhoehen, wenn du den Wert *nicht* gefunden hast.
nick21
User
Beiträge: 11
Registriert: Freitag 23. März 2018, 09:28

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: ascii -*-

item = ["a","b","a","c","b","a"]
print item
def enumerate_unique(iterable):
    count = 0 
    seen = dict()
    n=1
    for item in iterable:
        if item in seen:
            dict.get(item)   # gibt Value ( Nummer) zum entsprechenden Listeneintrag         
            item[count] = dict.get(item)                  # schreibt an die Stelle Count der Liste item das value
            yield count, item
        else: 
            n=n+1            # wenn Listeintrag nicht vorhanden, erzeuge Nummer 2   
            dict[item] = n   # Listeintrag wird neu hinzugefuegt mit Nummer 2
            yield count, item
        count=count+1
    print n
    print "Value : %s" % dict.values()
In beiden Fällen ist nun ein yield als return vorhanden. Das herausgelesen Value wird an die Position Count der Liste item geschrieben. Wenn ich es ausführe, passiert leider gar nichts
__deets__
User
Beiträge: 14536
Registriert: Mittwoch 14. Oktober 2015, 14:29

Jetzt sehe ich erst - statt count nimmst du n. Ist ja auch ok, aber warum dann Count rumstehen lassen?

Und jetzt hast du mal n, mal count. Und was soll denn item[count] bewirken?
nick21
User
Beiträge: 11
Registriert: Freitag 23. März 2018, 09:28

n soll nur für den Fall da sein, wenn ein neuer Eintrag in dem dict angelegt werden soll.

Bsp:

Liste = ["a","a","a","b"]

Dabei ist beim ersten Durchlauf Count =0 die if Bedingung nicht erfüllt und die Zahl n wird um 1 erhöht. Somit n=1. Damit wird nun ein dict Eintrag angelegt mit key=a, value=1. Nächster Durchlauf: Count=1. Der key a ist im dict vorhanden, if Bedingung ist erfüllt. Erst beim 4. Durchlauf, Count =3 ist die if Bedingung erneut nicht erfüllt. n erhöht sich um 1, somit n=2. Der neue Eintrag bekommt den Eintrag key=b, value=2.

Code: Alles auswählen

 l = [1, 0.5, "Hallo Welt", 2]

 l[3] = "foo bar"


item[Count] habe ich für das Ändern des Wertes in der List verwendet. item als Listname und [Count] als die aktuelle Stelle, an der der neue Wert geschrieben werden soll
__deets__
User
Beiträge: 14536
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du hast dich da voellig verhaspelt.

Du brauchst *eine* Zaehlvariable, die du immer dann hochzaehlst, wenn du einen *neuen* Wert bekommst. Und du gibst immer ein Tupel zurueck mit yield aus aus aktuellem Element und entweder der Zaehlvariable, oder dem Wert im seen dict *FUER DAS ELEMENT*, nicht irgendeinen counter.
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@nick21: es tut mir leid, das sagen zu müssen, aber Du hast Dich völlig verrannt. Wenn man beim Programmieren eine Zeile nicht verstanden hat, was sie tut, dann hilft es nicht, weitere Zeilen dazuschreiben, in der Hoffnung, der Computer würde den Menschen irgend wann verstehen, wenn man ihm nur oft genug sagt, was man will.

Am besten löschst Du alles, und fängst von vorne an, und benutzt nur solche Konstrukte, die die kennst. Versuche, mit vielen print-Anweisungen versehen, den weiter oben beschriebenen Algorithmus Schritt für Schritt umzusetzen, und immer wieder zu testen, ob das Programm das macht. was Du erwartest.

Erster Schritt wäre, eine Schleife zu schreiben, die Listenelemente und einen Zähler ausgibt. Zweiter Schritt, zu jedem Eintrag diesen mit dem Zähler in ein Wörterbuch schreiben und jeweils das Wörterbuch auszugeben, und zu prüfen, ob in jedem Schleifendurchgang das drin steht, was Du erwartest. Dann kommt der nächste Schritt, ...
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

@nick21: Was bei dem bisherigen Ansatz nicht bedacht wurde, ist, dass die items im seen-dict zu keys werden, aber nicht alle Datentypen als key genutzt werden können. Daher ist zu beachten, über was genau Du später iterieren möchtest.
nick21
User
Beiträge: 11
Registriert: Freitag 23. März 2018, 09:28

Danke für die Tipps und die Hilfe. Ich fange Montag dann nochmal in Ruhe an.
Antworten