Posts: 4,646
Threads: 1,493
Joined: Sep 2016
a list might be like [[1,2,3],4,[5,6,7,8],[9]] and i want to flatten it to [1,2,3,4,5,6,7,8,9] . how easy is this to do if it is only 2 levels like that? what if it goes even deeper like [[1,2,3],4,[5,[[6,7],8]],[9]] . is it any easier as a list than any type of iterator? would this be any easier if the iterators were ranges?
Tradition is peer pressure from dead people
What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Posts: 2,953
Threads: 48
Joined: Sep 2016
There is a generator function here. Look at it.
Posts: 4,646
Threads: 1,493
Joined: Sep 2016
looking for something simpler. i think i am getting close.
Tradition is peer pressure from dead people
What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Posts: 1,950
Threads: 8
Joined: Jun 2018
Aug-06-2018, 06:03 AM
(This post was last modified: Aug-06-2018, 06:03 AM by perfringo.)
This could be simpler and should work:
>>> m = [[1,2,3],4,[5,[[6,7],8]],[9]]
>>> def flatten(lst):
... for item in lst:
... try:
... yield from flatten(item)
... except TypeError:
... yield item
...
>>> list(flatten(m))
[1, 2, 3, 4, 5, 6, 7, 8, 9] I should mention that if list contains string(s) function fails miserably (maximum recursion depth exceeded)
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy
Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Posts: 4,646
Threads: 1,493
Joined: Sep 2016
Aug-06-2018, 06:40 AM
(This post was last modified: Aug-06-2018, 07:37 AM by Skaperen.)
you could test for list type somewhere to avoid trying to iterate a string.
* Skaperen thinks that code would be a great example for the language reference
that code gave me hints, but i wanted something that would also work in Python2, so no yield from. i came up with this code, which works without being a generator at all. i created it as a code file with test code, instead of an interactive session, since i wanted to keep it.
flatten.py: def flatten(*a):
if len(a)==1:
l=[]
flatten(a[0],l)
return l
if isinstance(a[0],list):
for e in a[0]:
flatten(e,a[1])
return
a[1].append(a[0])
return
x=[[1,2,3],4,[5,[[6,7],8]],[9]]
print(repr(x))
y=flatten(x)
print(repr(y))
Tradition is peer pressure from dead people
What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Posts: 2,953
Threads: 48
Joined: Sep 2016
(Aug-06-2018, 06:03 AM)perfringo Wrote: I should mention that if list contains string(s) function fails miserably (maximum recursion depth exceeded) I had this issue with strings. You can see the link in my prev. post.
I like the way you use try/except. I didn't even think to catch an exception.
Posts: 1,950
Threads: 8
Joined: Jun 2018
Aug-06-2018, 09:46 AM
(This post was last modified: Aug-06-2018, 09:46 AM by perfringo.)
Let's bend our minds little further
This should be compatible with Python 2 and handle strings as well:
def flatten(lst):
def _flatten(lst, result):
if type(lst) is not list:
result.append(lst)
else:
for item in lst:
result = result + flatten(item)
return result
return _flatten(lst, []) This will produce:
>>> n = [[1, 2, 3], [[4]], [5], [['spam','ham','bacon'] , [['foo','bar','baz']], ['x','y','z']], 6]
>>> flatten(n)
[1, 2, 3, 4, 5, 'spam', 'ham', 'bacon', 'foo', 'bar', 'baz', 'x', 'y', 'z', 6]
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy
Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Posts: 8,148
Threads: 159
Joined: Sep 2016
Aug-06-2018, 10:18 AM
(This post was last modified: Aug-06-2018, 10:18 AM by buran.)
def flatten(lst):
result = []
for item in lst:
if isinstance(item, (list, tuple)): # You may add more container types if needed
result.extend(flatten(item))
else:
result.append(item)
return result
n = [[1, 2, 3], [[4]], [5], [['spam','ham','bacon'] , [['foo','bar','baz']], ('x','y','z')], 6]
print flatten(n) Output: [1, 2, 3, 4, 5, 'spam', 'ham', 'bacon', 'foo', 'bar', 'baz', 'x', 'y', 'z', 6]
Posts: 1,950
Threads: 8
Joined: Jun 2018
(Aug-06-2018, 10:18 AM)buran Wrote: def flatten(lst):
result = []
for item in lst:
if isinstance(item, (list, tuple)): # You may add more container types if needed
result.extend(flatten(item))
else:
result.append(item)
return result
This is the reason I like Python - smart people (like buran) can achieve desired results with minimal and very readable piece of code. I have lot of work to do in smart part
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy
Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Posts: 4,779
Threads: 76
Joined: Jan 2018
Aug-06-2018, 10:35 AM
(This post was last modified: Aug-06-2018, 10:35 AM by Gribouillis.)
Using a generic function to dispatch according to the argument's type
>>> import functools
>>> @functools.singledispatch
... def flatten(x):
... return [x]
...
>>> @flatten.register(list)
... @flatten.register(tuple)
... def _(x):
... return [z for y in x for z in flatten(y)]
...
>>> a = [[1, 2, 3], [[4]], [5], [['spam','ham','bacon'] , [['foo','bar','baz']], ('x','y','z')], 6]
>>> flatten(a)
[1, 2, 3, 4, 5, 'spam', 'ham', 'bacon', 'foo', 'bar', 'baz', 'x', 'y', 'z', 6]
|