@Patejoker: Da brauchst Du einen richtigen Parser für, da laut Beispiel ja auch verschachtelte Tupel vorkommen können. Und mit Fehlern müsste der dann auch umgehen können, denn im Beispiel im Quelltext als Kommentar stimmt die Klammerung nicht.
Die `check()`-Funktion macht viel mehr als etwas zu prüfen. Was eine Funktion macht, sollte aus dem Namen ersichtlich sein. Zudem verändert sie globalen Zustand, womit es keine reine Funktion mehr ist. Alles was eine Funktion verwendet was keine Konstanten sind, sollte als Argument übergeben werden und Ergebnisse als Rückgabewerte an den Aufrufer zurückgegeben werden. Sonst erfüllen Funktionen nicht den Zweck in sich geschlossene, isolierte Teilaufgaben zu erfüllen, die man leicht nachvollziehen und testen kann.
Auf Modulebene sollte sowieso nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Dann kommt man auch gar nicht erst in die Versuchung in einer Funktion oder Methode irgendwelchen globalen Zustand benutzen oder gar verändern zu wollen. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.
`i` als Laufvariable in einer Schleife sollte nur für ganze Zahlen verwendet werden. Alles andere ist sehr überraschend und verwirrend.
*Alle* Ausnahmen mit einem nackten ``except:`` zu behandeln ist fast immer falsch und kann die Fehlersuche enorm erschweren. Man sollte immer nur konkret die Ausnahmen behandeln die man auch erwartet, sonst werden auch alle unerwarteten so behandelt und man bekommt nicht mit was da genau passiert ist, sondern wundert sich am Ende nur über unerwartete/falsche Ergebnisse und muss dann erst einmal anfangen zu suchen.
Typprüfung mit ``type(obj) == some_type`` ist nicht gut. Dafür ist die `isinstance()`-Funktion gedacht. Die Prüfung macht auch erst Sinn wenn denn tatsächlich andere Datentypen ausser Zeichenketten hereinkommen können. *Dann* würde man aber auch erwarten das Zahlen schon als Zahlen vorliegen und nicht mehr geparst werden müssen.
Als Wort wird alles angesehen was nicht ganze Zahl, Tuple, Liste, oder Zeichenkette der Länge 1 ist. Also da wird kein Test gemacht ob es sich um eine Zeichenkette handelt. Das würde ich prüfen und einen ``else``-Zweig ans Ende packen der Alarm schlägt wenn die Funktion auf etwas trifft was nicht den Erwartungen entspricht.
`bubblesort()` kannst Du rauswerfen: Listen haben eine `sort()`-Methode.
Die ``while``-Schleife dort wäre übrigens eher eine ``for``-Schleife, beziehungsweise würde man die bei einer ernsthaften Implementierung eher durch ein Flag ersetzen das anzeigt ob es Vertauschungen gab. Denn die Länge der Eingabedaten ist in diesem Fall ja der „worst case“, in der Regel kann man früher abbrechen.
Die ``while``-Schleife auf Modulebene ist keine Schleife da der Schleifenkörper grundsätzlich genau *einmal* ausgeführt wird. Also weg damit.
Nach der Eingabe entfernst Du eckige und runde Klammern. Damit hat sich jegliche Möglichkeit erledigt Listen und Tupel zu erkennen.
Ich würde dann ungefähr bei so etwas landen (ungetestet):
Code: Alles auswählen
from __future__ import absolute_import, division, print_function
def partition(values):
numbers = list()
letters = list()
words = list()
def recurse(values):
for value in values:
try:
numbers.append(int(value))
except ValueError:
if isinstance(value, (list, tuple)):
recurse(value)
elif isinstance(value, str):
if len(value) == 1:
letters.append(value)
else:
words.append(value)
else:
raise ValueError(
'unexpected value {0!r} of type {1}'.format(
value, type(value)
)
)
recurse(values)
return numbers, letters, words
def main():
#1,2,3,(4,5,6),7,[Hallo,Danke,Bitte),a,b,c,d,g,e,(a,(b,[c],e),a),n
eingabe = input(
'Bitte geben Sie das ihre Daten ein getrennt durch ein ,\n'
'Ihr Eingabe bitte:'
)
for charachter in '()[]':
eingabe = eingabe.replace(charachter, '')
liste = eingabe.split(',')
results = partition(liste)
for result in results:
result.sort()
numbers, letters, words = results
print('Es wurden folgende Zahlen eingegeben', numbers)
print('Es wurden folgende Buchstaben eingegeben', letters)
print('Es wurden folgende Worte eingegeben', words)
if __name__ == '__main__':
main()
Wie schon gesagt ist das Stichwort hier Parser. Als erstes stellt sich da die Frage ob Du am Eingabeformat etwas ändern kannst. Du sprichst von Listen und Tupeln als wenn es Python wäre, die Beispiel enthalten dann aber Buchstaben und Zeichenketten die nicht der Pythonsyntax entsprechen. Würden sie das tun, also Beispielsweise ``['Hallo','Welt']`` statt ``[Hallo,Welt]``, dann könnte man einfach `ast.literal_eval()` aus der Standardbibliothek verwenden um die Eingabe zu parsen.
Wenn man am Format der Eingabe nichts ändern kann könnte man sich selbst einen einfachen Parser schreiben, also beispielsweise mit dem `re`-Modul die Eingabe in Token zerlegen und dann einen „recursive descent“-Parser schreiben.
Oder, und das würde ich wohl machen, man nimmt eines der Python-Packages zum bauen von eigenen Parsern. Ich benutze da fast immer PyParsing, es gibt aber auch andere.