itertools.flatten()? and copying generators/iterators.
Peter Otten
__peter__ at web.de
Tue Oct 28 05:21:29 EST 2003
Raymond Hettinger wrote:
> Core itertools should be primitive building blocks that combine with one
> another to make other tools. Also, I'm trying to keep the toolset as
> small as possible by excluding new tools that can be easily and
> efficiently coded in pure python.
>
> I would code it like this:
>
> def flatten(s):
> try:
> iter(s)
> except TypeError:
> yield s
> else:
> for elem in s:
> for subelem in flatten(elem):
> yield subelem
>
> As your examples show, it does have some suprising behavior in that
> strings get split apart instead of staying intact. That is easily taken
> care of by an AtomicString subclass:
>
> class AtomicString(str):
> def __iter__(self):
> raise TypeError
>
> a = [1, 2, AtomicString('abc'), 4]
>
>
>
>> >>> # The following I'm not sure what to do about...
>> >>> empty = [1, [], 3]
>> >>> emptyiter = [1, iter([]), 3]
>
I suggest a minor modification:
def flatten(s, toiter=iter):
try:
it = toiter(s)
except TypeError:
yield s
else:
for elem in it:
for subelem in flatten(elem, toiter):
yield subelem
def keepstrings(seq):
if isinstance(seq, basestring):
raise TypeError
return iter(seq)
sample = [1, 2, [3, "abc def".split()], 4]
print sample
print list(flatten(sample, keepstrings))
print list(flatten([1, [], 3]))
print list(flatten([1, iter([]), 3]))
The above handles strings in a way that is nonintrusive on client code.
Peter
More information about the Python-list
mailing list