This flattenizes any nested level list. I couln't find this in itertools module so I wrote it. Python 3 may be required.
1 2 3 4 5 6 7 8 9 10 | def deepFlatten(lista):
'''
>>> list(deepFlatten([1,2,[], [1], 3, [4, [5,6]], 7, 'oi', None])) => [1, 2, 1, 3, 4, 5, 6, 7, 'o', 'i', None]
'''
try:
for item in lista:
for one in deepFlatten(item):
yield one
except:
yield lista
|
The best I've been able to come up with thus far is:
The "best" solution would seem to me to be:
but I keep getting the following warnings:
Exception RuntimeError: 'maximum recursion depth exceeded while calling a Python object' in <type 'exceptions.TypeError'> ignored
Anyone know why I get that error? Even with just 2 "levels" of flattening to do, I hit a recursion depth error, which seems incorrect.
@Matthew Wood:
For the same reason that the str special case is in the recipe. Iterating a string produces strings of length 1. Since 'o' is an iterable of length 1, deep_flatten('o') will keep stepping into the try clause without ever generating a TypeError.
-1 for not working in the general case.
By checking types, you limit yourself to a finite number of classes that will "work" here. Without using ABCs (which won't always work) you have to limit yourself to either a finite number of stringlike objects, or a finite number of non-stringlike iterables.
You know what works waaay better than this recipe? Not being in a situation where you have to flatten arbitrarily-nested iterables in the first place. It's less common and more easily-avoidable than you think, and then you don't get into awful situations like this.
Good points so we can recall the solution from Matthew with a small modification:
def deepFlatten(lista): try: for item in lista: for one in deepFlatten(item): yield one except: yield lista
Just remove the exception object 'TypeError'