Flatten a list
Python, 49 lines
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
def flattenlist(L): import types WhiteTypes = ('StringType', 'UnicodeType', 'StringTypes', 'ListType', 'ObjectType', 'TupleType') BlackTypes= tuple( [getattr(types, x) for x in dir(types) if not x.startswith('_') and x not in whites] ) tmp =  def core(L): if not hasattr(L,'__iter__'): return [L] else : for i in L: if isinstance(i,BlackTypes): tmp.append(i) continue if type(i) == type(str()): tmp.append(i) else: core(i) return tmp return core(L) #Examples x=[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[['x']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] >>> flattenlist(x) ['x'] >>> x=(((((1))))) >>> flattenlist(x)  >>> x=[(),(),] >>> flattenlist(x)  >>> x=[(1),('1'),[1.0]] >>> flattenlist(x) [1, '1', 1.0] >>> x=[[[[[[(((([1,1]))))]]]]]] >>> flattenlist(x) [1, 1] >>> x=1 >>> flattenlist(x)  >>> x=flattenlist >>> flattenlist(x) [<function flattenlist at 0x16a8320>] >>>
inspired by http://code.activestate.com/recipes/363051-flatten/
it's a combination of recursion and closures it always return a list either cropped down to one level or if the input is small just a list wrapped around it
Note : in line 17 it just checks if it is instance of any of the types we need
i hope you like it :-)
I don't like how it makes certain assumptions about the structure of the
typesmodule and uses the module to generate a blacklist by subtracting a predefined whitelist. But more importantly,
evalis evil and should be avoided,
getattris better suited in this case.
You could probably sanitize that bit a bit like so:
Or if you want to avoid one-liners:
This will still break if the module ever contains anything that is not a
tuple, btw) and is not prefixed, though. To fix this you could add the restriction
type(x) == type(or
type(x) != typein the verbose version).
Other than that it is very concise and pretty solid.
That function is quite big to do something so simple!
I made this other function some time ago, which as I just tested my self, does everything yours does.
Hope you don't mind! -Sunjay03
Alan Plum Thanks for your Comment while the rest of the code is doing was it supposed to do , yes it's true my assumptions about the types module makes the code bad...
I totally agree that it needs to add some simpler white and blacklist "handling" ... as you proposed . i was just concentrated only on the core function and i totally forget to clean it up so not to put this very bad bad line --> Types =dir(types)[:-5] )-:
I totally regret i will not do it again ;) :-) :P Anyway thanks for your words
Sunjay Varma My intention was to make my version of flattenlist using closures because from what i saw there where already being made other solutions (recursive,recursive-iterator,for loop etc...)from other people .
My version just came up like this because i wasn't concern about less lines of code and i am pretty sure i can make a smaller version if that is my intention
I updated the code
It's much easier to just assume that everything with an __iter__ is a valid iterator and once you talk about iterator rather than lists you can minify the flatten function to this:
Should a list flattener flatten strings? Or tuples? ...
Answer to Paddy:
The API is wrong. It is upto to the caller to determine which types are atomic. In some circumstances, strings and tuples should be recursed into, and in other circumstances it might not be useful at all.
I come from a lisp background and this is what I came up with: