list.lower() oder dict.upper() etc.

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.
Pythonierer
User
Beiträge: 41
Registriert: Samstag 13. Januar 2007, 15:26

list.lower() oder dict.upper() etc.

Beitragvon Pythonierer » Samstag 9. Februar 2008, 01:33

Guten Abend!

Ich bin gerade dabei, ein "virtuelles" Hackspiel zu programmieren, das ausschließlich in der Shell abläuft. Nun habe ich mir ein Dictionary angelegt, in dem jeweils der Wert eines Ordners oder einer Datei das Parentverzeichnis ist. Nun soll man über "CD Ordner" in den Ordner gelangen:

ordner ist die Eingabe nach CD, self.comp das Dictionary, in welchem jeweils der Schlüssel ein/e Ordner/Datei und der Wert das Parentverzeichnis ist. self.path ist der Arbeitspfad links des blinkenden Cursors im Cmd.

if ordner in self.comp.keys() and self.comp[ordner]==self.path.split('/')[-2] and ordner.count('.')==0:
self.path+=ordner+'/'

Erst wird geprüft, ob ordner als Unterverzeichnis existiert, danach ob sein Parentverzeichnis dem aktuellen Arbeitsverzeichnis entspricht und dann, ob ordner keine Datei ist.

Das ganze funktioniert ja prima, wenn ich einfach alle Ordner im Dictionary groß bzw. klein schreibe und dann die Eingabe ordner auch per .upper() oder .lower() groß- bzw. klein mache. Doch wie sollte ich am klügsten vorgehen, dass ich die Groß- und Kleinschreibung als "Hacker" ignorieren kann, ohne meine Ordner nur aus Groß- oder Kleinbuchstaben zusammensetzen zu müssen? Natürlich könnte ich immer mit einer for-Schleife self.comp.keys() etc. vorübergehend lowern oder uppern, aber dies würde eine Menge Code produzieren.

Gibt es eine Möglichkeit, eine Liste bzw. ein Dictionary ähnlich .lower() und .upper() von der Schreibweise zu ändern oder ist es möglich, eine Bedingung in folgendem Format aufzustellen:

if re.compile(ordner, re.IGNORECASE) in self.comp.keys()...

Danke für euer Interesse,

Pythonierer!
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Beitragvon audax » Samstag 9. Februar 2008, 10:44

Auch, wenn es dein Problem nicht löst:
Keine Case-insensitive Kommandos und Ordner!
Ich hasse sowas....und steh da glaube ich nicht alleine da...

Zum Problem:
Normalisiere deine Eingaben: userinput.upper() !
Pythonierer
User
Beiträge: 41
Registriert: Samstag 13. Januar 2007, 15:26

Beitragvon Pythonierer » Samstag 9. Februar 2008, 13:10

Danke audax für die Antwort, jedoch bringt mich letztere nicht wirklich weiter.

Einerseits benötige ich case-insensitive Kommandos, da es ja CMD simulieren soll, in welchem es nunmal so ist. Ich selbst finde case-sensitive Befehle auch viel besser, doch will ich nun mal die Windows System-Shell simulieren, nicht die von Linux.
Andererseits hilft auch der Tipp mit dem uppern des Userinputs nicht, da ja weiterhin die Ordner im Dictionary groß- bzw. klein geschrieben sind. Und dass ich letztere nicht auch standardisiert groß- bzw. klein schreiben will, hab ich ja schon erwähnt. Es soll eben alles wie in der cmd.exe ablaufen.

Ich hoffe, dass ihr noch ein paar kreative Ratschläge auf Lager habt und verbleibe mit freundlichen Grüßen,

Pythonierer!
Jan-Peer
User
Beiträge: 166
Registriert: Dienstag 2. Oktober 2007, 10:55

Beitragvon Jan-Peer » Samstag 9. Februar 2008, 13:17

Wenn ich mich richtig erinnere, unterscheidet Windows - und damit auch cmd - nicht zwischen "verzeichnis" und "Verzeichnis". Demzufolge wäre es möglich, sowohl die Eingabe als auch den Verzeichnisnamen für den Vergleich (und nur dort) mit upper() oder lower() zu behandeln.
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Beitragvon audax » Samstag 9. Februar 2008, 13:38

Code: Alles auswählen

class Directory (dict):
    def __init__(self, *data):
        super(Directory, self).__init__(data)
        self.list = [i.upper() for i in self.keys()]

    def __contains__(self, key):
        return key.upper() in self.list


Code: Alles auswählen

>>my_dict = Directory(('foo', ['bar', 'foo']), ('bar', ['fooz']))

>>print my_dict.list
['FOO', 'BAR']
>>print 'FoO' in my_dict
True
>>print my_dict.keys()
['foo', 'bar']


€dit:
Ja ich weiß, man müsste die Liste immer updaten...Aber meine Güte: Das kommt dann halt in die Funktionen Directory.mkdir() und Directory.addFile()
BlackJack

Beitragvon BlackJack » Samstag 9. Februar 2008, 15:10

Mit einem `set()` statt einer Liste ist der ``in``-Test bei vielen Verzeichnissen schneller. Und `self.list` sollte einen Namen bekommen der ausdrückt wozu das Ding da ist, und nicht welchen Typ es hat. Würde bei einem `set` ja sowieso nicht mehr stimmen.

Auf `super()` würde ich verzichten. Zu kompliziert ohne echten Gewinn.
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Beitragvon audax » Samstag 9. Februar 2008, 15:24

Bargh...Meckerbacke :p

Code: Alles auswählen

class Directory (dict):
    def __init__(self, *data):
        self.update(data)
        self._upperKeys = set([i.upper() for i in self.keys()])

    def __contains__(self, key):
        return key.upper() in self._upperKeys


Code: Alles auswählen

In [2]: from directory import Directory

In [3]: my_dict = Directory(('foo', ['bar', 'foo']), ('bar', ['fooz']))

In [4]: print my_dict._upperKeys
set(['FOO', 'BAR'])

In [5]: print 'FoO' in my_dict
True

In [6]: print my_dict.keys()
['foo', 'bar']
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Beitragvon Y0Gi » Samstag 9. Februar 2008, 15:40

Die eckigen Klammern im `set`-Aufruf bei `_upperKeys` *hust* PEP 8-Namen *hust* kannst du auch weglassen, so dass eine speicherfreundlichere Generator Expression verwendet wird.
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Beitragvon audax » Samstag 9. Februar 2008, 16:13

Code: Alles auswählen

class Directory (dict):
    def __init__(self, *data):
        self.update(data)
        self._upperKeys = set(i.upper() for i in self.keys())

    def __contains__(self, key):
        return key.upper() in self._upper_keys

Code: Alles auswählen

In [1]: from directory import Directory

In [2]: my_dict = Directory(('foo', ['bar', 'foo']), ('bar', ['fooz']))

In [3]: print 'FoO' in my_dict
True

Und seit wann geht denn das set(<generator expression>)?

€dit:
Grad gefunden: Seit 2.4
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Beitragvon Y0Gi » Samstag 9. Februar 2008, 16:22

Genau genommen ist es `set((.. for .. in ..))`, womit analog zu List Comprehensions runde statt eckiger Klammern verwendet werden. Allerdings können die inneren runden Klammern entfallen, sofern - wie eben bei bei Übergabe an Callables - äußere runde Klammern vorhanden sind.

Wer ist online?

Mitglieder in diesem Forum: Bing [Bot]