Seite 1 von 1

nested sequences - Entnestnung

Verfasst: Dienstag 25. September 2007, 20:59
von le_bub
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

Re: nested sequences - Entnestnung

Verfasst: Dienstag 25. September 2007, 21:17
von gerold
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
:-)

Verfasst: Dienstag 25. September 2007, 21:42
von 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']

Verfasst: Mittwoch 26. September 2007, 05:15
von mawe
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.

Verfasst: Mittwoch 26. September 2007, 08:14
von Rebecca
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]

Verfasst: Mittwoch 26. September 2007, 09:42
von 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!

Verfasst: Mittwoch 26. September 2007, 19:21
von birkenfeld
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.

Verfasst: Donnerstag 27. September 2007, 13:36
von le_bub
Herzlichen Dank wieder mal fuer eure Hilfe,

bub

Verfasst: Donnerstag 27. September 2007, 14:38
von poker
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.

Verfasst: Donnerstag 27. September 2007, 14:40
von mitsuhiko
Ich würde eine "isnewiter = lambda x: hasattr(x, '__iter__')" funktion basteln.

Verfasst: Donnerstag 27. September 2007, 14:53
von poker
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

Verfasst: Donnerstag 27. September 2007, 15:13
von 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.

Verfasst: Donnerstag 27. September 2007, 15:32
von mitsuhiko
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 :-)

Verfasst: Donnerstag 27. September 2007, 15:39
von 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/

Verfasst: Donnerstag 27. September 2007, 17:02
von birkenfeld
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.

Verfasst: Freitag 28. September 2007, 09:21
von poker
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.

Verfasst: Freitag 28. September 2007, 09:30
von mitsuhiko
Mein Fehler. Zumindest haben jetzt Strings ein __iter__.

Verfasst: Freitag 28. September 2007, 12:39
von 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.