nested sequences - Entnestnung

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
le_bub
User
Beiträge: 8
Registriert: Donnerstag 13. September 2007, 12:22

Halloechen!

Wiedermal ne Anfaengerfrage von mir:

Wie kommt man den bitte auf elegante Art und Weise von

liste = [('a', 'b', 'c'), ('a', 'l', 'h'), ('m', 'h', 'a')

auf

liste = ['a', 'b', 'c', 'a', 'l'. 'h', 'm', 'h', 'a'] ?

Vielen Dank fuer nen kleinen Tipp,

leBub
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hallo le_bub!

Z.B. so:

Code: Alles auswählen

>>> liste = [('a', 'b', 'c'), ('a', 'l', 'h'), ('m', 'h', 'a')]
>>> flache_liste = []
>>> for item in liste:
...     flache_liste.extend(item)
...     
>>> flache_liste
['a', 'b', 'c', 'a', 'l', 'h', 'm', 'h', 'a']
>>>
mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
lunar

Oder so:

Code: Alles auswählen

from itertools import chain

items = [('a', 'b', 'c'), ('a', 'l', 'h'), ('m', 'h', 'a')]
flattened = list(chain(*items))
print flattened
# >> ['a', 'b', 'c', 'a', 'l', 'h', 'm', 'h', 'a']
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

Oder so:
[wiki]Tipps und Tricks#Listen[/wiki]-> Verschachtelte Listen glätten

PS: Ich wollte eigentlich direkt auf die betreffende Seite verlinken, aber mit dem "ä" gabs Schwierigkeiten.
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Mein Firefox zeigt Sonderzeichen in Adresszeile in der %-Schreibweise an, also Verschachtelte_Listen_gl%C3%A4tten, damit klappts dann:

[wiki]Verschachtelte Listen glätten[/wiki]
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
lunar

Der rekursive Generator hat aber einen kleinen Fehler, der in in diesem Fall, bei dem die inneren Listen Tupel sind, untauglich macht:

Code: Alles auswählen

def flatten(lst):
    for elem in lst:
        # diese Überprüfung schlägt fehl! Tupel sind keine Listen!
        if isinstance(elem, list):
            for i in flatten(elem):
                yield i
        else:
            yield elem
Es müsste also isinstance(elem, (list, tuple)) heißen!
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Die Typüberprüfung ist eh fraglich. Normalerweise versucht man einfach, zu iterieren und fängt einen Fehler ab. Gut, da ist wieder eine Typüberprüfung notwendig, diesmal für Strings.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
le_bub
User
Beiträge: 8
Registriert: Donnerstag 13. September 2007, 12:22

Herzlichen Dank wieder mal fuer eure Hilfe,

bub
poker
User
Beiträge: 146
Registriert: Donnerstag 20. September 2007, 21:44

Hi,

ich kann mich da nur der Meinung von Birkenfeld anschließen.

Mein Code den ich mir gebaut habe und immer in den utils habe ist folgender:

Code: Alles auswählen

def isiterable(v, exclude_string=True):
    if exclude_string and isinstance(v, basestring):
        return False
    try:
        iter(v)
    except:
        return False
    return True


def flatten(iterable):
    for x in iterable:
        if isiterable(x):
            for y in flatten(x):
                yield y
        else:
            yield x
Unterstützt das Ducktyping sehr. `isiterable` habe ich absichtlich so definiert das man strings mit `exclude_string` ausschließen kann.

Wem das zu lang ist, hier zusammengehackt:

Code: Alles auswählen

def flatten(iterable):
    def isiterable(v):
        if isinstance(v, basestring): return False
        try:iter(v)
        except: return False
        else: return True

    for x in iterable:
        if isiterable(x):
            for y in flatten(x):
                yield y
        else:
            yield x
BTW: Wenn man ausschließen kann das im iterable kein strings vorhanden sind, bin ich ganz klar für die erste Lösung von Lunar.
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Ich würde eine "isnewiter = lambda x: hasattr(x, '__iter__')" funktion basteln.
TUFKAB – the user formerly known as blackbird
poker
User
Beiträge: 146
Registriert: Donnerstag 20. September 2007, 21:44

Yes!! Viel eleganter und schneller. Thx :)

edit:
Ich glaube, dass kann man nun ins Wiki schieben ;)

Code: Alles auswählen

def flatten(iterable):
    for x in iterable:
        if hasattr(x, "__iter__"):
            for y in flatten(x):
                yield y
        else:
            yield x
BlackJack

Das reicht nicht weil es 1. iterierbare Objekte gibt, die keine `__iter__()` Methode besitzen und 2. nur "Zufall" ist, dass Zeichenketten dazu gehören.
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

BlackJack hat geschrieben:Das reicht nicht weil es 1. iterierbare Objekte gibt, die keine `__iter__()` Methode besitzen und 2. nur "Zufall" ist, dass Zeichenketten dazu gehören.
Also erstens fliegt diese Art der Iteration mit Python3 raus, und zweitens würde ich gerne wissen wo du solche Objekte rumliegen hast :-)
TUFKAB – the user formerly known as blackbird
BlackJack

In Dateien auf meiner Festplatte. ;-) Die entstehen ab und zu ganz beiläufig wie zum Beispiel die `Namen`-Klasse hier: http://paste.pocoo.org/show/3954/
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

blackbird hat geschrieben:
BlackJack hat geschrieben:Das reicht nicht weil es 1. iterierbare Objekte gibt, die keine `__iter__()` Methode besitzen und 2. nur "Zufall" ist, dass Zeichenketten dazu gehören.
Also erstens fliegt diese Art der Iteration mit Python3 raus
Da wäre ich mir nicht sicher. Bisher ist es noch vorhanden, und es steht auch nicht in PEP 3100 als zu entfernen.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
poker
User
Beiträge: 146
Registriert: Donnerstag 20. September 2007, 21:44

BlackJack hat geschrieben:In Dateien auf meiner Festplatte. ;-) Die entstehen ab und zu ganz beiläufig wie zum Beispiel die `Namen`-Klasse hier: http://paste.pocoo.org/show/3954/
Haha, jetzt weiß ich auch wider warum ich das damals mit ``iter`` implementiert habe. :D Eben wo ich dein Post gelesen habe, konnte ich mich wider wage erinnern, das ich das damals auch so wie blackbird gemacht habe und auf die fresse gefallen bin. -- Klar, iterable ist alles was entweder das ``__iter__, next, __getitem__`` Protokoll implementiert (Ich hoff die Aufzählung ist vollständig).
blackbird hat geschrieben:Also erstens fliegt diese Art der Iteration mit Python3 raus,
Und? 3.0 ist noch garnicht raus und wenn, dann werden viele erst auf 2.6 umsteigen wenn es raus kommt.

OT: Ich würde ja mal am liebsten 2.6 links liegen lasen und dann gleich auf 3.0 umsteigen. Tjoa, wenn da auch alle Entwickler mitspielen würden. IMO wird es **sehr** lange dauern bis die Entwickler ihre Libs mit 3.0 kompatibel machen.
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Mein Fehler. Zumindest haben jetzt Strings ein __iter__.
TUFKAB – the user formerly known as blackbird
BlackJack

@poker: Ich denke 2.6 ist wichtig für den Umstieg auf 3.0 weil da möglichst viel aus der 3.0 übernommen wird was keine Probleme mit der Rückwärtskompatibilität bringt. So kann man den "harten" Bruch von 2.6 auf 3.0 etwas milder gestalten.
Antworten