Eine Funktion zum Vertauschen von Schlüssel und Wert (Dict.)

Code-Stücke können hier veröffentlicht werden.
Antworten
ASCII158
User
Beiträge: 80
Registriert: Samstag 28. September 2002, 15:40
Wohnort: München

Dieses Forum sieht so traurig aus ohne Beiträge, deswegen bekommt ihr hier mal was zum zerfleddern :wink::

Code: Alles auswählen

def swapdict(dict):
	"""swapdict(dict) -> dict
	Vertauscht die Schlüssel und Werte eines Dictionaries. Wenn ein Wert mehr als einmal vorkommt werden die dazugehoerigen Schlüssel in einer Liste mit diesem Wert verbunden.
	Turns value to key and the other way round. If a value appears more than one time the keys are set to a list and associated with the value."""
	
	import types
	redict={}
	for i in dict.keys():
		if dict[i] in redict.keys():
			if type(redict[dict[i]])==type(types.TupleType()):
				redict[dict[i]]+=(i,)
			else:
				redict[dict[i]]=(redict[dict[i]],i,)
		else:
			redict[dict[i]]=i
	return redict
mfg,

10011110
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Hallo 111111!
ASCII158 hat geschrieben:Dieses Forum sieht so traurig aus ohne Beiträge, deswegen bekommt ihr hier mal was zum zerfleddern :wink::
Mein Vorschlag (allerding mit Listen, nicht mit Tupel):

Code: Alles auswählen

redict = {}
for key,value in dict.items():
    try:
        try:
            redict[value].append(key)
        except:
            redict[value] = [redict[value],key]
    except:
        redict[value] = key
Warum erst fragen (if), wenn man es doch gleich versuchen kann (try)?
Ok, im RL tut man sich dabei weh, wenn man gegen die Tür rennt und sie dann erst öffnet, aber dem Rechner ist das egal :-)

Jan
ASCII158
User
Beiträge: 80
Registriert: Samstag 28. September 2002, 15:40
Wohnort: München

Ich heisse 10011110! :lol:

Warum erst fragen (if), wenn man es doch gleich versuchen kann (try)?
Daran merkt man, dass man zulange mit Basic "rumgeschweinst" hat... :roll:

Ich bestehe aber weiterhin auf den Tuples:

Code: Alles auswählen

for key,value in dict.items(): 
		try: 
			try: 
				redict[value]+=(key,) 
			except: 
				redict[value] = (redict[value],key)
		except: 
			redict[value] = key
mfg,

10011110
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Hallo 10001011!

[quote="ASCII158"]Ich heisse 10011110! :lol: [quote]
Für jahrelange Usenet-Nutzer wie mich sind diese k3wlen Pseudos in den Web-Foren etwas gewöhnungsbedürfig und meist auch der Hauptgrund, sie (die Web-Foren) zu meiden. Naja, nicht Euer Problem.

Jan
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Hallo!
ASCII158 hat geschrieben: Ich bestehe aber weiterhin auf den Tuples:
Was mir noch auffiel, da Du das Ganze wohl zur Wiederverwendung in eine Funktion packst. Um es etwas sauberer zu gestalten, sollte man nur die konkreten Exceptions bearbeiten, damit die anderen nach oben weitergereicht werden.

Code: Alles auswählen

        except TypeError:
            [...]
    except KeyError:
Zudem überblicke ich so auf die Schnelle nicht, was passiert, wenn im Ausgangs-Dictionary die Schlüssel und/oder Werte was anderes sind, als Strings oder Zahlenwerte, also z.B. Listen oder Dictionaries.

Jan
ASCII158
User
Beiträge: 80
Registriert: Samstag 28. September 2002, 15:40
Wohnort: München

Hi,
Voges hat geschrieben: Zudem überblicke ich so auf die Schnelle nicht, was passiert, wenn im Ausgangs-Dictionary die Schlüssel und/oder Werte was anderes sind, als Strings oder Zahlenwerte, also z.B. Listen oder Dictionaries.
Funktioniert alles, nur natürlich nicht Listen im Value, weil die kein Key werden können!
mfg,

10011110
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Hallo!
ASCII158 hat geschrieben:Funktioniert alles,
Leider nicht. xy-Koordinaten kommen ja häufig als Schlüssel vor. Und aus ...
dict = {(2,4):'rot',(1,3):'rot',(6,7):'blau',(2,5):'rot',(7,7):'gelb'}
... wird leider ...
{'blau': (6, 7), 'gelb': (7, 7), 'rot': (2, 4, (2, 5), (1, 3))

Da ist wohl doch noch etwas Feinarbeit nötig.

Jan
ASCII158
User
Beiträge: 80
Registriert: Samstag 28. September 2002, 15:40
Wohnort: München

Darin liegt der Sinn dieses Forums, Fehler zu finden!

Aber eine Korrektur fällt mir dazu so auf die Schnelle auch nicht ein...
mfg,

10011110
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hallo,

mal den Thread wiederbeleb.
Mit Python ab Version 2.2 geht das tauschen von Schlüssel/Wert auch mit einem Einzeiler:

Code: Alles auswählen

test = {(1,3) : 'rot', (6,7) : 'blau', (7,7) : 'gelb', (4,6) : 'gruen'}
print dict([(b, a) for a, b in test.items()])
Nachteil, wenn Werte doppelt vorkommen, wird irgendein Paar genommen.


Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

HI. Mit Python 2.4 gehts auch komplett mit Iteratoren :wink: . Allerdings dürfen nach wie vor keine Dicts oder Listen als Value vorkommen...

Code: Alles auswählen

test = {(1,3) : 'rot', (6,7) : 'blau', (7,7) : 'gelb', (4,6) : 'gruen'}
print dict( (b, a) for a, b in test.iteritems() )
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

dat geht auch mit 2.3, hab an iteritems gar nicht gedacht :)


Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Hi. Schau es dir genau an :wink: --- es ist keine List Comprehension...
Olliminatore

Dookie hat geschrieben:Hallo,
mal den Thread wiederbeleb.
[...]
Nachteil, wenn Werte doppelt vorkommen, wird irgendein Paar genommen.
Hat jemand eine Lösung ohne diesen Nachteil?

Also wenn ein Key doppelt ist soll dessen Value an den anderen angehängt werden.(also nicht gelöscht)
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Olliminatore hat geschrieben:
Dookie hat geschrieben: Nachteil, wenn Werte doppelt vorkommen, wird irgendein Paar genommen.
Hat jemand eine Lösung ohne diesen Nachteil?
Also wenn ein Key doppelt ist soll dessen Value an den anderen angehängt werden.(also nicht gelöscht)
Hi!
Ist das ursprüngliche, erste Beispiel nicht das was du brauchst?
lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Olliminatore
User
Beiträge: 55
Registriert: Montag 30. Mai 2005, 16:03
Wohnort: schönsten Stadt Deutschlands
Kontaktdaten:

Ja fast :oops: war schon müde, (dachte sie hat kleinen Fehler)
Ausserdem brauche eine Funktion die einfach und schnell ist, da ich mit grossen Zahlenwerten arbeite :).
python 2.2
Hier mein Vorschlag für ein einfaches dict (type müsste egal sein)habe halben Tag dran gesessen :shock:

Code: Alles auswählen

## Dictionary zu Liste wandeln 
MapL = dict.iteritems()
## Schluessel/Werte umdrehen und Werte in Liste wandeln
MapL= [(b, [a]) for a, b in MapL]
MapL.sort()    ## Ordnung muss sein
Listshort=[("",[""])]

for value, key in MapL:
    if value != Listshort[-1][0]:
        Listshort.append([value, key])
    else:
        Listshort[-1][1].extend(key)

## und wieder zurück von Liste zu Dictonary
redict=dict(Listshort[1:])
geht auch oder? Kann sein dass es noch einfacher geht. Teste jetzt noch bisschen...
(value und key namen könnten ungünstig gewählt sein, halt umgedreht) :roll:

edit: (als member ist echt komfortabler hier)
ohne else geht auch, weiss aber nicht ob dass schneller ist mit pop(), vieleicht geht nochn Einzeiler? :P (list comprehension ist noch nicht so mein ding)

Code: Alles auswählen

[...snipped...]
habs mit Dookies List Benchmark getestet. Die pop() Variante war 4mal langsamer :!:
Olliminatore
User
Beiträge: 55
Registriert: Montag 30. Mai 2005, 16:03
Wohnort: schönsten Stadt Deutschlands
Kontaktdaten:

Habe mal alle Varianten mitn Benchmark durchgetestet.
ASCII158: mit try: und tuple war (minimal schlechter) gleich Voges: mit list.
Interessant ist mit

Code: Alles auswählen

        except TypeError:
            [...]
    except KeyError:
um 1/3 schneller war :!:

Wobei meine Variante (für meine Zwecke) noch 7mal schneller war als Diese .
Scheinbar weil ich keine Type/Key Abfrage mache.
Olliminatore
User
Beiträge: 55
Registriert: Montag 30. Mai 2005, 16:03
Wohnort: schönsten Stadt Deutschlands
Kontaktdaten:

Code: Alles auswählen

def dictinvert(d):
    inv = {}
    for k, v in d.iteritems(): inv.setdefault(v, []).append(k)
    return inv
Das ist was ich gesucht habe(dict) ! :D
Da gilt wieder: Wer sucht der findet , aber wann!?
Meine List Variante ist aber immernoch doppelt so schnell.
Antworten