Elemente einer hierarchischen Listenstruktur annotieren

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
Benutzeravatar
lucia
User
Beiträge: 8
Registriert: Mittwoch 7. Januar 2009, 17:59

Hallo :)
Ich möchte, Elemente in einer hierarchischen Listenstruktur mit ihrem jeweiligen Python-Typ annotieren. Nur klappt das mit dem hierarchisch leider nicht.

Code: Alles auswählen

>>> for e in [8, "a", [(2,3), "die katze", 0], 2+3]:
	print (type(e), e)

	
(<type 'int'>, 8)
(<type 'str'>, 'a')
(<type 'list'>, [(2, 3), 'die katze', 0])
(<type 'int'>, 5)
Ich würde gerne die Liste in der Liste als Tupel, String und Integer angezeigt bekommen. Hat jemand einen Tipp für mich?
Entschuldigung wegen des sehr uneleganten Stils, blutige Anfängerin :oops:
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

Code: Alles auswählen

In [60]: for e in [8, "a", [(2,3), "die katze", 0], 2+3, {'zahl': 23, 'sinn_des_lebens': 42}]:
    if isinstance(e, (list, tuple)):
        for item in e:
            print (type(item), item)
    elif isinstance(e, dict):
        for value in e.itervalues():
            print (type(value), value)
    else:
        print (type(e), e)
   ....:         
   ....:         
(<type 'int'>, 8)
(<type 'str'>, 'a')
(<type 'tuple'>, (2, 3))
(<type 'str'>, 'die katze')
(<type 'int'>, 0)
(<type 'int'>, 5)
(<type 'int'>, 42)
(<type 'int'>, 23)
Mit isinstance kann man prüfen, ob ein Objekt von der vermuteten Klasse instanziiert wurde. list, int, type, dict, ... sind nämlich auch nichts anderes als Klassen.

Edit: @lucia: habe ich dich falsch verstanden?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

derdon, da würde man eher erst prüfen ob es ein dict ist und dann ein ``iteritems()`` machen, dann würde man versuchen ob es iterierbar ist (es gibt durchaus iterierbare Typen die keine Listen oder Tupel sind) und erst wenn auch das fehlschlägt, dann den Typ vom Objekt nehmen. Wenn beim dict auch nur die Keys reichen, kann man das mit den Iterables zusammenlegen.

Ggf würde man hier sogar rekursiv vorgehen, wenn die Liste wiederrum eine Liste enthält, etc.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
lucia
User
Beiträge: 8
Registriert: Mittwoch 7. Januar 2009, 17:59

Im Grunde möchte ich anstatt

Code: Alles auswählen

(<type 'int'>, 8)
(<type 'str'>, 'a')
(<type 'list'>, [(2, 3), 'die katze', 0])
(<type 'int'>, 5)
folgendes bekommen:

Code: Alles auswählen

(<type 'int'>, 8)
(<type 'str'>, 'a')
(<type 'tuple'>, (2,3))
(<type 'str'>, 'die katze')
(<type 'int'>, 0)
(<type 'int'>, 5)

Ich würde mich gerne spezifischer ausdrücken,
aber dafür fehlt mir wohl noch das Fachvokabular, sorry :oops:
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Code: Alles auswählen

IGNORE = (basestring, tuple)

def deepmap(func, itr):    
    if isinstance(itr, IGNORE):
        return (func(itr), itr)
    else:
        try:
            return [deepmap(func, elem) for elem in itr]
        except TypeError:
            return func(itr)
    
def annotate(elem):
    return (type(elem), elem)
            
test = [8, "a", [(2,3), "die katze", 0], 2+3]

print deepmap(annotate, test)
Das ergibt:

Code: Alles auswählen

[(<type 'int'>, 8), ((<type 'str'>, 'a'), 'a'), [((<type 'tuple'>, (2, 3)), (2, 3)), ((<type 'str'>, 'die katze'), 'die katze'), (<type 'int'>, 0)], (<type 'int'>, 5)]
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Und nochmal ganz anders:

Code: Alles auswählen

def deepmap(func, itr, ignore=None):
    if itr is ignore:
        return (func(itr), itr)
    else:
        try:
            return [deepmap(func, elem, itr) for elem in itr]
        except TypeError:
            return func(itr)
    
def annotate(elem):
    return (type(elem), elem)
            
test = [8, "a", [(2,3), "die katze", 0], 2+3]

print deepmap(annotate, test)
Er schaut sich jetzt _jedes_ iterable an, verfällt aber nicht in eine Endlosschleife.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

lucia hat geschrieben:Im Grunde möchte ich anstatt

Code: Alles auswählen

(<type 'int'>, 8)
(<type 'str'>, 'a')
(<type 'list'>, [(2, 3), 'die katze', 0])
(<type 'int'>, 5)
folgendes bekommen:

Code: Alles auswählen

(<type 'int'>, 8)
(<type 'str'>, 'a')
(<type 'tuple'>, (2,3))
(<type 'str'>, 'die katze')
(<type 'int'>, 0)
(<type 'int'>, 5)

Ich würde mich gerne spezifischer ausdrücken,
aber dafür fehlt mir wohl noch das Fachvokabular, sorry :oops:
Wie das geht, ist doch eben gezeigt worden, oder übersehe ich jetzt was? :roll:
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

Leonidas hat Recht, diese Aufgabe schreit geradezu nach Rekursion. Wer möchte der erste sein?

Edit: Sorry, audax. Hab mir deinen Code ehrlich gesagt nicht so genau angeguckt.
Zuletzt geändert von derdon am Mittwoch 7. Januar 2009, 19:58, insgesamt 1-mal geändert.
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Ich fühl mich ignoriert.

Also gut, jetzt noch geflattet:

Code: Alles auswählen

def annotate_list(itr):
    if isinstance(itr, list):
        return [annotate_list(elem) for elem in itr]
    else:
        return (type(itr),itr)

def flatten(x):
    """ http://kogs-www.informatik.uni-hamburg.de/~meine/python_tricks """
    result = []
    for el in x:
        if hasattr(el, "__iter__") and \
          not isinstance(el, (tuple, basestring)):
            result.extend(flatten(el))
        else:
            result.append(el)
    return result    
              
            
test = [8, "a", [(2,3), "die katze", 0], 2+3]

print flatten(annotate_list(test))
Ergebnis:

Code: Alles auswählen

[(<type 'int'>, 8), (<type 'str'>, 'a'), (<type 'tuple'>, (2, 3)), (<type 'str'>, 'die katze'), (<type 'int'>, 0), (<type 'int'>, 5)]
Zuletzt geändert von audax am Mittwoch 7. Januar 2009, 19:03, insgesamt 1-mal geändert.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

audax Lösung ist rekursiv.
Benutzeravatar
lucia
User
Beiträge: 8
Registriert: Mittwoch 7. Januar 2009, 17:59

@audax: Wow, das ist genau das Ergebnis, das ich haben wollte. Vielen, lieben Dank.
Ich versuch' mich jetzt mal durch den Code zu kämpfen, um es auch verstehen.

Vielen Dank für die schnelle Hilfe!
Antworten