Zugriff by reference auf verschachtelte Liste

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
Gerenuk
User
Beiträge: 69
Registriert: Donnerstag 21. Januar 2010, 22:27

Oh, bin gerade fleißig beim programmieren und hoffe jemand findet folgende Frage interessant :)

Ich wollte mir ein normalize programmieren, dass folgendes macht

Code: Alles auswählen

def normalize(l, aggregate=sum, norm_by=operator.truediv):
   aggregated=aggregate(l)
   for i in range(len(l)):
       l[i]=norm_by(l[i], aggregated)
Nun ist es aber komplizierter, wenn ich verschachtelte Liste habe wie a[x][y] und eigentlich über x normalisieren will. Also effektiv

Code: Alles auswählen

aggregated=sum(a[i]["const"] for i in range(len(a)))
for i in range(len(a)):
  a[i]["const"]/=aggregated
Ich vermute fast irgendwas mit gettern und settern und so Tricks könnte das Problem lösen. Bloß so auf Anhieb fällt mir da nix ein :(
Ideen?
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Ja und was ist jetzt dein Problem?
Gerenuk
User
Beiträge: 69
Registriert: Donnerstag 21. Januar 2010, 22:27

Na ich kann schreiben

Code: Alles auswählen

l=[1,2,3,4]
normalize(l)
Aber was mache ich wenn

Code: Alles auswählen

l=[[1,0],[2,0],[3,0],[4,0]]
und ich will l[x][0] mit einer externen function über x normalisieren? Also dass ich normalize irgendwie auf l anwende, so dass l=[[0.1,0],[0.2,0],[0.3,0],[0.4,0]] rauskommt.

Da fällt mir keine clevere Lösung ein...
Gerenuk
User
Beiträge: 69
Registriert: Donnerstag 21. Januar 2010, 22:27

Hmm, also genial wäre ja

Code: Alles auswählen

normalize(l[...][0])
Bloß kann man das mit Python so zusammenhacken? Klingt anspruchsvoll...
BlackJack

@Gerenuk: Ich finde die API für Python-Verhältnisse etwas ungewöhnlich. Das ``for i in range(len(l)):`` ist ein Wink mit dem Zaunpfahl, dass das nicht wirklich "pythonisch" ist. In der Regel erzeugt man in Python in solchen Fällen eine neue Liste und verändert nicht die Alte.

Ansonsten könnte `numpy` hier wahrscheinlich eine Lösung sein, denn dort kann man solche "slices" sicher machen.
BlackJack

Mit `numpy`:

Code: Alles auswählen

In [100]: a = np.array([[1, 0], [2, 0], [3, 0], [4, 0]], float)

In [101]: b = a[...,0]

In [102]: b /= b.sum()

In [103]: a
Out[103]: 
array([[ 0.1,  0. ],
       [ 0.2,  0. ],
       [ 0.3,  0. ],
       [ 0.4,  0. ]])
Gerenuk
User
Beiträge: 69
Registriert: Donnerstag 21. Januar 2010, 22:27

@BlackJack:
Naja, pythonisch ist was am Ende cool ist :)
Und manchmal möchte man halt in-place bearbeiten.

Also numpy ist ja krass. Sowas in der Art müsste ich für lists und dicts nachprogrammieren :) Jemand eine Ahnung wie das ungefähr geht?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Gerenuk hat geschrieben:@BlackJack:
Naja, pythonisch ist was am Ende cool ist :)
Dem muss ich widersprechen. Pythonisch ist, was dem Zen von Python folgt. Also mal `import this` lesen.
Gerenuk hat geschrieben:Und manchmal möchte man halt in-place bearbeiten.
Da empfiehlt sich `enumerate`.
Gerenuk hat geschrieben:Also numpy ist ja krass. Sowas in der Art müsste ich für lists und dicts nachprogrammieren :) Jemand eine Ahnung wie das ungefähr geht?
Also ich wuerde da ja mal bei numpy schaun ..
Gerenuk
User
Beiträge: 69
Registriert: Donnerstag 21. Januar 2010, 22:27

cofi hat geschrieben: Dem muss ich widersprechen. Pythonisch ist, was dem Zen von Python folgt. Also mal `import this` lesen.
In Python kann man Listen nicht anders als mit "for i in range(len(l))" bearbeiten, wenn es per Referenz sein soll. Das ist also sehr wohl pythonisch und ist in allen Beispielsammlungen.

Naja, ich hatte noch ne super Idee was ich implementieren werde. Ich mache mir eine Klasse
Miter(d, "key1", ..., "key2", ..., 1, "key3")
und schreibe dazu getitem, setitem und iter so dass sich das ganze verhält wie ein dict a[x,y] <-> d["key1"][x]["key2"][y][1]["key3"] :)

Das ist mal richtig pythonisch und erlaubt sehr dynamische Programmierung. An normalize muss ich dafür nichts mehr ändern und sämtlich Funktionen die nichts anderes als einfache dicts kennen, werden damit umgehen können :)

OK, numpy gab dir Idee vor ;)
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Gerenuk hat geschrieben:
cofi hat geschrieben:Dem muss ich widersprechen. Pythonisch ist, was dem Zen von Python folgt. Also mal `import this` lesen.
In Python kann man Listen nicht anders als mit "for i in range(len(l))" bearbeiten, wenn es per Referenz sein soll. Das ist also sehr wohl pythonisch und ist in allen Beispielsammlungen.
Das Bezog sich in erster Linie auf deine Definition von "pythonisch". Aber wenn das nicht anders geht, dann ist folgender Code wohl nicht lauffähig:

Code: Alles auswählen

def normalize(l, aggregate=sum, norm_by=operator.truediv):
   aggregated = aggregate(l)
   for i, e in enumerate(l):
       l[i] = norm_by(e, aggregated)
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Gerenuk hat geschrieben:
cofi hat geschrieben: Dem muss ich widersprechen. Pythonisch ist, was dem Zen von Python folgt. Also mal `import this` lesen.
In Python kann man Listen nicht anders als mit "for i in range(len(l))" bearbeiten, wenn es per Referenz sein soll. Das ist also sehr wohl pythonisch und ist in allen Beispielsammlungen.
Den Hinweis zu enumerate hast du aber schon gelesen, oder?
Gerenuk hat geschrieben:Naja, ich hatte noch ne super Idee was ich implementieren werde. Ich mache mir eine Klasse
Miter(d, "key1", ..., "key2", ..., 1, "key3")
und schreibe dazu getitem, setitem und iter so dass sich das ganze verhält wie ein dict a[x,y] <-> d["key1"][x]["key2"][y][1]["key3"] :)[/code]
Was immer du vor hast, wenn du Dictniaries so verschachtelt aufbaust, dann machst du mit Sicherheit etwas falsch. Wahrscheinlich möchtest du Klassen und mehr Funktionen benutzen.[/code]
Gerenuk hat geschrieben:Das ist mal richtig pythonisch und erlaubt sehr dynamische Programmierung. An normalize muss ich dafür nichts mehr ändern und sämtlich Funktionen die nichts anderes als einfache dicts kennen, werden damit umgehen können :)[/code]
Wo ist so eine Struktur denn übersichtlich? Dynamische Programmierung ist übrigens nicht das, was du glaubt was es ist ;-)

OK, numpy gab dir Idee vor ;)
Das Leben ist wie ein Tennisball.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Gerenuk hat geschrieben:In Python kann man Listen nicht anders als mit "for i in range(len(l))" bearbeiten, wenn es per Referenz sein soll. Das ist also sehr wohl pythonisch und ist in allen Beispielsammlungen.
Also ganz oft ist in Python das Zurückgeben von veränderten Listen pythonischer als das ändern ebendieser. Aber das nur nebenbei.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten