Listenelemente ersetzen

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
Peak_me
User
Beiträge: 92
Registriert: Sonntag 27. Januar 2008, 03:09

huhu!

Um die Übersicht zu verbessern, mach ich mal nen neuen Thread auf.

Aufgrund der Anregungen aus den anderen beiden Threads habe ich nun begonnen, mir was über iterieren und Schleifen durchzulesen um mein Programm von den Schleifenungetümen zu befreien.
Doch bei einem Fall habe ich Probleme:

Liste a enthält sehr viele Zahlen in dem Format:
a=[[1,2,7,8],[3,4,7,9],[8,3,2,2]....]
Liste b enthält Buchstaben:
b=['a','b','c','d','e','f','g','h',...]

Die Zahlen in a sollen nun durch Buchstaben aus b nach folgendem Muster ersetzen werden:
0>a
1>b
2>c
3>d
...

Die Zahlenliste a soll aber erhalten bleiben.

Dies hatte ich so gelöst:

Code: Alles auswählen

a1=list(a)
for i in range(len(a1)):
    for j in range(len(a1[i])):
        a2=list(a1[i])
        a2[j]=b[a2[j]]
        a1[i]=a2
Nun habe ich es so gemacht:

Code: Alles auswählen

a1=list(a)
for i in a1:
    for j,k in enumerate(i):
        i[j]=b[k]
Das Problem ist nur, dass die ursprüngliche Liste "a", die ja unverändert bleiben soll, doch verändert wird.
Dies hatte ich im alten Programm durch a2=list(a1) verhindert.

Ich habe es dann mit deepcopy probiert:

Code: Alles auswählen

a1=copy.deepcopy(a)
for i in a1:
    for j,k in enumerate(i):
        i[j]=b[k]
So funktioniert es.

Doch dauert das "deepcopy" zu lange. Ich optimiere mein Programm ja gerade dazu, um es schneller zu machen.
Der alte und der neue Abschnitt sind nun wegen des "deepcopy"s aber wieder fast gleich langsam.
Ich habe mir mal die Laufzeitveränderung angeschaut:

Code: Alles auswählen

a=[[1,1,2],[1,2,2]]
for i in range(100000):
    Zeile x
mit Zeile x gleich
"b=list(a)"
Laufzeit:0,08 s

mit Zeile x gleich
"b=copy.copy(a)"
Laufzeit:0,27 s

mit Zeile x gleich
"b=copy.deepcopy(a)"
Laufzeit:2,45 s

Hat jemand eine Lösung für mein Problem?
Ich bräuchte entweder eine schnellere Kopier-Methode oder eine Möglichkeit, die Listenelemente zu ersetzen, ohne dass das Problem auftritt oder eine andere Lösung :)


Gruß
Paul
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Wieso erzeugst Du nicht einfach eine neue Liste und befüllst diese innerhalb der Schleife? Imho das einfachste, eleganteste und vermutlich das schnellste!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

Erstelle einfach eine neue Liste durch anhängen oder "list comprehension" und nicht durch kopieren und ersetzen von Elementen.

Code: Alles auswählen

In [85]: a = [[1, 2, 7, 8], [3, 4, 7, 9], [8, 3, 2, 2]]

In [86]: b = string.ascii_lowercase

In [87]: c = [[b[x] for x in xs] for xs in a]

In [88]: c
Out[88]: [['b', 'c', 'h', 'i'], ['d', 'e', 'h', 'j'], ['i', 'd', 'c', 'c']]
Peak_me
User
Beiträge: 92
Registriert: Sonntag 27. Januar 2008, 03:09

Ich dachte, dass wenn ich eine neue Liste während der Verarbeitung erstellen würde, dies erheblich langsamer wäre, weil ich sowas immer mit x.append(y) mache.

An diese Ausdrücke c = [[b[x] for x in xs] for xs in a] muss ich mich erstmal gewöhnen.
Er weiß hierbei also automatisch, dass er für jeden Schleifendurchlauf das jeweilige Element zu "c" hinzufügen soll.

Diese Lösung ist in der Tat die schnellste.
danke!

PS:
Da es nicht viel Zeit braucht, habe ich es erstmal nicht beachtet.
Aber da wir gerade dabei sind und es nun direkt unter dieser Zeile steht, kann ich es ja mal ansprechen.

Die Liste c hat ja jetzt das Format "[['a','a','a',],['a','a','a',],['a','a','a',]].
Daraus soll nun [aaa,aaa,aaa] werden.

Das hatte ich so gemacht:

Code: Alles auswählen

for i in range(len(c)):
        c[i]=''.join(c[i]) 
Jetzt könnte man es ja so machen:

Code: Alles auswählen

for i in c:
        i=''.join(i)
Doch so verändert er ja c nicht mehr.

Mit enumerate ginge es dann wieder:

Code: Alles auswählen

for i,j in enumerate(c):
    c[i]=''.join(j)
Doch ich vermute, dass es da wieder eine einzeilige und bessere Variante geben wird.

Vielleicht könnte man es ja auch direkt in c = [[b[x] for x in xs] for xs in a] einbauen.
BlackJack

@Peak_me: Klar kann man das auch gleich einbauen:

Code: Alles auswählen

In [89]: [''.join(b[x] for x in xs) for xs in a]
Out[89]: ['bchi', 'dehj', 'idcc']
Ansonsten würde ich auch einfach wieder eine neue Liste mit einer "list comprehension" aus `c` erstellen, oder etwas kürzer ausgedrückt die `map()`-Funktion verwenden:

Code: Alles auswählen

In [90]: [''.join(xs) for xs in c]
Out[90]: ['bchi', 'dehj', 'idcc']

In [91]: map(''.join, c)
Out[91]: ['bchi', 'dehj', 'idcc']
karolus
User
Beiträge: 144
Registriert: Samstag 22. August 2009, 22:34

Hallo

Code: Alles auswählen

a= [[1,2,7,8],[3,4,7,9],[8,3,2,2]]
b = [ ''.join( chr ( 97 + x ) for x in teil ) for teil in a ]
Gruß Karo
Peak_me
User
Beiträge: 92
Registriert: Sonntag 27. Januar 2008, 03:09

@BlackJack:
aha!

Ich hatte versucht, es direkt einzubauen und u.a. das probiert:
[''.join(b[x]) for x in xs for xs in a]

So joint er natürlich immer nur einen Buchstaben, was sinnlos ist, aber ich dachte, dass er vielleicht das wieder aufs große Ganze übertrüge :roll:

Die Klammer um die betreffende Schleife zu setzen ist natürlich die richtige Lösung!
war ich bloß nicht drauf gekommen...

@karolus
Auch ne gute Lösung, in meinem Programm sind die Buchstaben aber nicht in einer alphabetischen Reihenfolge, sondern gemischt.
Antworten