Seite 1 von 1

Inverses itertools.tee(), quasi izip() ohne Tupel gesucht

Verfasst: Dienstag 22. März 2011, 17:13
von Hyperion
Hallo zusammen,

wie kann man das folgende Problem elegant lösen? Ich versuche es mal in der von itertools bekannten Kurzschreibweise klar zu machen:

Code: Alles auswählen

func(p, q, ...) 	p0, q0, ... p1, q1, ... plast, qlast, ... 	
# z.B.
func('ABC', 'DEF') --> A D B E C F
Gesucht ist also eine Funktion, die sich jeweils das erste Element der gegeben Iterables nimmt, dieses zurückliefert und anschließend mit dem nächsten Element weitermacht usw. bis schließlich alle Elemente konsumiert wurden (inkl. ggf. nötiger Füllwerte bei ungleicher Länge).

Ich habe es mit Hilfe der flatten()-Funktion aus dem Brownie-Paket gelöst:

Code: Alles auswählen

In [8]: from itertools import izip_longest

In [9]: from brownie.itools import flatten

In [10]: a, b = range(5), range(5, 9)

In [11]: a, b
Out[11]: ([0, 1, 2, 3, 4], [5, 6, 7, 8])

In [12]: list(flatten(izip_longest(a, b)))
Out[12]: [0, 5, 1, 6, 2, 7, 3, 8, 4, None]
Also als Funktion dann z.B.:

Code: Alles auswählen

def merge(*iterables, **kwargs):
    fillvalue = kwargs.get('fillvalue')
    for item in flatten(izip_longest(*iterables, fillvalue=fillvalue)):
        yield item
Kann man das einfacher / eleganter lösen? Und wenn ja wie :-D

Re: Inverses itertools.tee(), quasi izip() ohne Tupel gesuch

Verfasst: Dienstag 22. März 2011, 17:19
von DasIch
Du kannst `brownie.functional.compose` nutzen:

Code: Alles auswählen

>>> from itertools import izip_longest
>>> from brownie.itools import flatten
>>> from brownie.functional import compose
>>> merge = compose(flatten, izip_longest)
>>> list(merge(range(5), range(5, 9)))
[0, 5, 1, 6, 2, 7, 3, 8, 4, None]

Re: Inverses itertools.tee(), quasi izip() ohne Tupel gesuch

Verfasst: Dienstag 22. März 2011, 17:35
von Hyperion
Danke, das spart ja noch das manuelle Wrappen in eine Funktion. Aber das Prinzip als solches bleibt damit erhalten - scheint also nicht so schlecht zu sein als Ansatz :-)

Re: Inverses itertools.tee(), quasi izip() ohne Tupel gesuch

Verfasst: Dienstag 22. März 2011, 22:23
von bords0
Oder so (Python 3):

Code: Alles auswählen

>>> a = range(5)
>>> b = range(5, 9)
>>> list(itertools.chain(*itertools.zip_longest(a, b, fillvalue="-")))
[0, 5, 1, 6, 2, 7, 3, 8, 4, '-']

Re: Inverses itertools.tee(), quasi izip() ohne Tupel gesuch

Verfasst: Mittwoch 23. März 2011, 06:48
von snafu
Wenn ich mich nicht täusche, entsteht beim Unpacking ein Tuple. Falls man diesen Zwischenschritt nicht haben möchte möchte, dann kann man auch ohne "Stern-Notation" über itertools.chain.from_iterable() gehen.