Iterable Flattener with Depth.

P

Pradeep Jindal

Hi,

5 minute solution to one of my requirements. I wanted to flatten
iterables upto a specific depth.
To be true, didn't search for it on the internet prior to writing this one.


def flatten_iter(my_iter, depth=None):
"""my_iter can be a iterable except string containing nested
iterables upto any depth. This function will flat all
(except string) down to a list containing all the elements in
nested-order.
To add to it you can specify optional depth (int or long)
argument and the
function will flatten the iterable upto that depth (nesting).
"""
if not hasattr(my_iter, '__iter__') or isinstance(my_iter, basestring):
return [my_iter]
elif depth != None and depth <= 0:
return my_iter
temp = []
for x in my_iter:
temp.extend(flatten_iter(x, None if depth == None else depth-1))
return temp

py> temp = [1,[2,[3,4,5],'bash'],6,[7,[8,[9,10,['hi', 'hello']]]], 11, 12]

py> flatten_iter(temp,1)

[1, 2, [3, 4, 5], 'bash', 6, 7, [8, [9, 10, ['hi', 'hello']]], 11, 12]

py> flatten_iter(temp,2)

[1, 2, 3, 4, 5, 'bash', 6, 7, 8, [9, 10, ['hi', 'hello']], 11, 12]

py> flatten_iter(temp)

[1, 2, 3, 4, 5, 'bash', 6, 7, 8, 9, 10, 'hi', 'hello', 11, 12]

py> flatten_iter(temp,3)

[1, 2, 3, 4, 5, 'bash', 6, 7, 8, 9, 10, ['hi', 'hello'], 11, 12]



Any comments?

Thanks
- Pradeep
 
B

bearophileHUGS

Pradeep Jindal:
Any comments?

Something with similar functionality (plus another 20 utility
functions/classes or so) has probably to go into the std lib... :)

Bye,
bearophile
 
P

praddy

Pradeep Jindal:


Something with similar functionality (plus another 20 utility
functions/classes or so) has probably to go into the std lib... :)

Bye,
bearophile

Same Here!

- Pradeep
 
I

Ian Clark

thebjorn said:
Yeah, everyone has to write a flatten sooner or later :) My version
is at:

http://blog.tkbe.org/archive/python-flatten/

-- bjorn

And here is mine. Note that it is very similar to Michael Spencer's
implementation[1]. The only difference is that this adds a depth counter.

def iflat(itr, depth=0):
itr = iter(itr)
stack = []
cur_depth = 0

while True:
try:
elem = itr.next()
if hasattr(elem, "__iter__") and cur_depth < depth:
stack.append(itr)
itr = iter(elem)
cur_depth += 1
else:
yield elem
except StopIteration:
if not stack:
raise StopIteration
cur_depth -= 1
itr = stack.pop()


if __name__ == "__main__":
test1 = ((0, 1, 2), ((3, 4), 5), (((6, 7), 8), 9))
test2 = [1,[2,[3,4,5],'bash'],6,[7,[8,[9,10,['hi', 'hello']]]], 11, 12]

for x in (test1, test2):
print
print list(iflat(x))
print
print list(iflat(x, 1))
print list(iflat(x, 2))
print list(iflat(x, 3))
print list(iflat(x, 4))
print iflat(x, 10)

Ian

[1] http://mail.python.org/pipermail/python-list/2005-March/312022.html
 
P

Pradeep Jindal

thebjorn said:
Yeah, everyone has to write a flatten sooner or later :) My version
is at:

http://blog.tkbe.org/archive/python-flatten/

-- bjorn

And here is mine. Note that it is very similar to Michael Spencer's
implementation[1]. The only difference is that this adds a depth counter.

def iflat(itr, depth=0):
itr = iter(itr)
stack = []
cur_depth = 0

while True:
try:
elem = itr.next()
if hasattr(elem, "__iter__") and cur_depth < depth:
stack.append(itr)
itr = iter(elem)
cur_depth += 1
else:
yield elem
except StopIteration:
if not stack:
raise StopIteration
cur_depth -= 1
itr = stack.pop()


if __name__ == "__main__":
test1 = ((0, 1, 2), ((3, 4), 5), (((6, 7), 8), 9))
test2 = [1,[2,[3,4,5],'bash'],6,[7,[8,[9,10,['hi', 'hello']]]], 11, 12]

for x in (test1, test2):
print
print list(iflat(x))
print
print list(iflat(x, 1))
print list(iflat(x, 2))
print list(iflat(x, 3))
print list(iflat(x, 4))
print iflat(x, 10)

Ian

[1] http://mail.python.org/pipermail/python-list/2005-March/312022.html

Very nice non-recursive (iterative) implementation of the thing with required
features. Yours is double faster than mine if depth is not specified, Mine is
double faster than yours if depth is specified. And my main aim was the depth
thingy. What do you think?

- Pradeep
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top