Seite 1 von 1

mehrdimensionale Listen

Verfasst: Donnerstag 31. Mai 2007, 15:37
von ronnyno
Hi !
Ich will einfach innerhalb einer Schleife ein Element einer zwei dimensionalen Liste durch das entsprechende einer anderen ersetzen, aber ich bekomme immer einen Fehler:

Traceback (most recent call last):
File "C:\Programme\Python25\renamer.py", line 27, in <module>
filelist[0]=filelistsave[0]
TypeError: 'str' object does not support item assignment


Hilfe !!!!!!! :-) Viele Gruesse, Ronny

Re: mehrdimensionale Listen

Verfasst: Donnerstag 31. Mai 2007, 15:46
von schlangenbeschwörer
Hi!
Die musst du lesen:
ronnynos Fehlermeldung hat geschrieben: Traceback (most recent call last):
File "C:\Programme\Python25\renamer.py", line 27, in <module>
filelist[0]=filelistsave[0]
TypeError: 'str' object does not support item assignment

Die letzte Zeile sagts doch: ´´filelist´´ (oder ´´filelist) ist keine Liste sondern ein String.
Für genauere Fehleranalyse und -behebung wär auch (mehr) Code nötig.

Gruß, jj

edit: der Fehler könnte natürlich auch von ´´filelistsave´´kommen.

Verfasst: Donnerstag 31. Mai 2007, 15:46
von Sr4l
Am besten Code posten.

Verfasst: Donnerstag 31. Mai 2007, 16:04
von ronnyno
ich will eigentlich nur die '_' in den Dateinamen entfernen, den Anfangsbuchstaben gross schreiben, sowie den Buchstaben nach dem '-'.
Dazu wollte ich eigentlich, wie im ein dimensionalen, einfach die Werte der Liste veraendern. Das ging in 2d aber irgendwie nicht. Hab dann die funktion replace gefunden, damit gings dann, damit ist es aber viel zu umstaendlich und sie macht auch nicht genau das, was ich will.

filelist= os.listdir(verz)
filelistsave=filelist

for i in range(0,len(filelist)):
filelist=filelist.replace('_',' ')
filelistsave=filelistsave.replace(filelistsave[0],string.upper(filelistsave[0]))
filelist[0]=filelistsave[0]
for j in range(0,len(filelist)):
if filelistsave[j]=='-':
filelistsave[i]=filelistsave[i].replace(filelistsave[i][j+2],string.upper(filelistsave[i][j+2]))
filelist[i][j+2]=filelistsave[i][j+2]

print os.listdir(verz)[i]+' -> '+filelist[i]
os.rename(verz+os.listdir(verz)[i],verz+filelist[i])

Verfasst: Donnerstag 31. Mai 2007, 16:12
von schlangenbeschwörer
1. So kann man den Code fast nicht lesen. -> Setz ihn bitte in [ (/)code ]-Tags.
2. Anstatt die Liste zu kopieren und dann irgedwie zu ändern, kannst du doch einfach in einer Schleife über die Ausgangsliste iritieren, jeden Wert wie gewünscht verändern und dann in einer neuen Liste speichern.
Das ist einfacher, lesbarer/verständlicher und ich denk auch mal weniger problematisch.

Verfasst: Donnerstag 31. Mai 2007, 16:16
von veers
Hinweis: Dir ist bewusst das du so:
filelistsave = filelist
Keine Kopie von filelist anfertigst sondern lediglich die Referenz kopierst?
Tipp: Kopieren geht so: filelistsave = list(filelist)
Tipp: range(0, N) == range(N)
Tipp: Lies dir mal den PEP 8 durch. So wird dein Code lesbarer.

Code: Alles auswählen

filelist = os.listdir(verz)
filelistsave = filelist

for i in range(0, len(filelist)):
	filelist[i] = filelist[i].replace('_', ' ')
    filelistsave[i] = filelistsave[i].replace(filelistsave[i][0], string.upper(filelistsave[i][0]))
    filelist[i][0] = filelistsave[i][0]
    for j in range(0, len(filelist[i])):
		if filelistsave[i][j] == '-':
			filelistsave[i] = filelistsave[i].replace(filelistsave[i][j + 2], string.upper(filelistsave[i][j + 2]))
            filelist[i][j + 2] = filelistsave[i][j + 2]
                        
        print os.listdir(verz)[i] + ' -> ' + filelist[i]
        os.rename(verz + os.listdir(verz)[i], verz + filelist[i])
So lässt sich das ganze zumindest schonmal besser lesen.

Verfasst: Donnerstag 31. Mai 2007, 16:17
von Sr4l
ronnyno hat geschrieben:

Code: Alles auswählen

        filelist= os.listdir(verz)
        filelistsave=filelist
        
        for i in range(0,len(filelist)):
            filelist[i]=filelist[i].replace('_',' ')
            filelistsave[i]=filelistsave[i].replace(filelistsave[i][0],string.upper(filelistsave[i][0]))
            filelist[i][0]=filelistsave[i][0]
            for j in range(0,len(filelist[i])):
                if filelistsave[i][j]=='-':
                    filelistsave[i]=filelistsave[i].replace(filelistsave[i][j+2],string.upper(filelistsave[i][j+2]))
                    filelist[i][j+2]=filelistsave[i][j+2]
                        
            print os.listdir(verz)[i]+' -> '+filelist[i]
            os.rename(verz+os.listdir(verz)[i],verz+filelist[i])
Dein Problem ist einfach. Du darfst nur in die zweite for-Schleife gehen wenn diese eine Liste ist. Wenn es ein String ist musst du diesen Punkt überspringen.

**edit**
oich rewrite mal

Verfasst: Donnerstag 31. Mai 2007, 16:27
von ronnyno
da ich noch absoluter Anfaenger bin, ist der restliche code eher verwirrend, deshalb habe ich ihn zuerst nicht gepostet.

ok, das problem mal einfacher:

liste=['hallo','welt']
liste[0][0]='a'
print liste

Warum funktioniert das nicht ?
( sollte dem Problem oben entsprechen, erhalte die gleiche Fehlermeldung)

Verfasst: Donnerstag 31. Mai 2007, 16:30
von veers
ronnyno hat geschrieben:da ich noch absoluter Anfaenger bin, ist der restliche code eher verwirrend, deshalb habe ich ihn zuerst nicht gepostet.

ok, das problem mal einfacher:

liste=['hallo','welt']
liste[0][0]='a'
print liste

Warum funktioniert das nicht ?
( sollte dem Problem oben entsprechen, erhalte die gleiche Fehlermeldung)
Weil Strings in Python imutable sind. Das heist du kannst sie nicht verändern ;)
Gehen würde:

Code: Alles auswählen

liste[0] = 'a' + liste[0][1:]
Falls du aber mal nicht das erste Element verändern willst sondern den String wirklich wie eine Liste behandeln willst: Mach draus einfach eine:

String2List:

Code: Alles auswählen

list("hello")
List2String:

Code: Alles auswählen

"".join(['h', 'e', 'l', 'l', 'o'])

Verfasst: Donnerstag 31. Mai 2007, 16:34
von ronnyno
das stand leider in keinem von den tuts die ich gelesen habe ... ( oder ich habs ueberlesen ... )

werd damit jetzt mal ein wenig rumexperimentieren :D

vielen dank euch allen !

Verfasst: Donnerstag 31. Mai 2007, 16:36
von Rebecca
Erstmal lege ich dir das hier ans Herz: http://www.python-forum.de/faq.php#21

Dein Problem ist, dass man Strings nicht veraendern kann.

Code: Alles auswählen

>>> a = "hallo"
>>> a[0] = "n"
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: object does not support item assignment
Du hast eben keine Liste von Listen, sondern eine Liste von Strings. Wenn du bestimmte Zeichen in Strings durch andere ersetzen willst, ist "replace" etwas fuer dich.

Code: Alles auswählen

>>> a.replace("l", "n")
'hanno'
>>>
Wenn du wirklich einen Buchstaben nach Index ersetzen willst, faellt mir gerade nur sowas ein:

Code: Alles auswählen

>>> "n%s" % a[1:]
'nallo'
EDIT: Ah ja, der Vorschlag von veer ist natuerlich schoener. :)

Verfasst: Donnerstag 31. Mai 2007, 16:38
von encbladexp
Und nochmal: Für Code immer eine Code-Block benutzen (deswegen heist der so!).

Warum sollte das was du versuchst auch funktionieren? Du hast eine Stinknormale Liste, auf die kannste mit

Code: Alles auswählen

liste[0]
zugreifen. Aber

Code: Alles auswählen

liste[0][0]
kann net gehen, weil ja das 0. Element der String hallo ist, und eben keine liste...

Eine deutlich bessere Lösung wurde ja schon weiter oben vorgeschlagen!

mfg Betz Stefan
edit: An dem das Stings nicht veränderbar sind ist auch was dran, hab den Code leider nicht so genau gelesen :-(

Verfasst: Donnerstag 31. Mai 2007, 16:52
von veers
Wieso sind Strings eigentlich immutable?

Was ich im Web gefunden habe ist das Strings nicht wachsen können weil das nicht explizit genug wäre. Das ist mir ja soweit klar. Wieso man einzelne Characters nicht ändern kann nicht.

Edit:
http://www.thescripts.com/forum/thread34919.html
Not being able to use strings as dictionary keys would kind of suck :)
Hm damit hat er wohl recht.

Verfasst: Donnerstag 31. Mai 2007, 16:59
von ronnyno
--- hat sich erledigt ---

Verfasst: Donnerstag 31. Mai 2007, 17:00
von Sr4l
natürlich geht [0][0], man kann den Index nur nicht verändern ;-)
Man könnten den String ja auch in ein Liste spliten jende Buchstaben aber naja hier meine Lösung:

Code: Alles auswählen

#!/usr/bin/python
#*~* coding: latin-1 *~*
import os
import string

filelist= os.listdir('/home/sr4l/test')
#filelistsave=filelist  #brauch ich nicht ^^
	
for i in range(len(filelist)):
	filelist[i]=filelist[i].replace('_',' ')
	filelist[i]= "".join([string.upper(filelist[i][0]),filelist[i][1:]])
	for j in range(len(filelist[i])-1):
			if filelist[i][j] == '-':
				filelist[i] = "".join([filelist[i][:j+1],string.upper(filelist[i][j+1]),filelist[i][j+2:]])

	#print os.listdir(verz)[i]+' -> '+filelist[i]
	#os.rename(verz+os.listdir(verz)[i],verz+filelist[i])
	print filelist
hätte ich den code geschreiben hätte ich filelist nur fl genannt (man ist das ein langes wort ;-) )
ach und PS das modul string braucht man kaum.
upper ist ein builtin und kann einfach per:

Code: Alles auswählen

>>> "lol".upper()
'LOL'
habs aber so gelassen.

Verfasst: Donnerstag 31. Mai 2007, 17:00
von veers
ronnyno hat geschrieben:also man hat a='hello' und will haben liste=['h','e','l','l','o']
veers hat geschrieben: String2List:

Code: Alles auswählen

list("hello")

Verfasst: Donnerstag 31. Mai 2007, 17:08
von ronnyno
prima jetzt laeufts einwandfrei !
und wieder viel dazugelernt :-)

Verfasst: Donnerstag 31. Mai 2007, 17:46
von BlackJack
Alternativlösung ohne die ganze Indexerei:

Code: Alles auswählen

import re

def main():
    filenames = ['foo - bar - baz']
    dash_re = re.compile(r'(- )(.)')
    result = list()
    for filename in filenames:
        filename = filename.replace('_', ' ').capitalize()
        filename = dash_re.sub(lambda m: m.group(1) + m.group(2).upper(),
                               filename)
        result.append(filename)
    print result
Mal vom regulären Ausdruck abgesehen etwas lesbarer.

Verfasst: Donnerstag 31. Mai 2007, 19:36
von veers

Code: Alles auswählen

Ix = MutableString("Foobar")
x[1]
>>>> 'o'
x[1] = '0'
x
>>>> 'F0obar'
Gibt also auch Mutable Strings ;)