Iterating through a nested list

C

CamelR

I have a newbie question, and I have seen reference to this mentioned
in many places, but all just say "this has been discussed frequently
in (other places) so we won't discuss it here..." and I am unable to
find the actual answer...

I expected :

Array = ["topdir", ["/subdir1", ["/file1", "/file2"], "/subdir2",
["/file1", "/file2"], "/subdir3", ["/file1", "/file2"]]]

for i in range(len(Array)):
print Array
for x in range(len(Array)):
print Array[x]
for y in range(len(Array[x])):
print Array[x][y]

to produce output like this:

topdir
['/subdir1', ['/file1', '/file2'], '/subdir2', ['/file1', '/file2'],
'/subdir3', ['/file1', '/file2']]
/subdir1
['/file1', '/file2']
/file1
/file2
/subdir2
['/file1', '/file2']
/file1
/file2
/subdir3
['/file1', '/file2']
/file1
/file2

but instead, it is iterating through each character in the elements,
like this:

topdir
t
t
o
o
p
p
d
d
i
i
r
r
['/subdir1', ['/file1', '/file2'], '/subdir2', ['/file1', '/file2'],
'/subdir3', ['/file1', '/file2']]
/subdir1
/
s
u
b
d
i
r
1
['/file1', '/file2']
/file1
/file2
/subdir2
/
s
u
b
d
i
r
2
['/file1', '/file2']
/file1
/file2
/subdir3
/
s
u
b
d
i
r
3
['/file1', '/file2']
/file1
/file2


so what am I doing wrong? I would really appreciate any advice or
pointers...

Thanks!
 
S

Steven D'Aprano

I have a newbie question, and I have seen reference to this mentioned
in many places, but all just say "this has been discussed frequently
in (other places) so we won't discuss it here..." and I am unable to
find the actual answer...

I expected :

Array = ["topdir", ["/subdir1", ["/file1", "/file2"], "/subdir2",
["/file1", "/file2"], "/subdir3", ["/file1", "/file2"]]]

for i in range(len(Array)):
print Array
for x in range(len(Array)):
print Array[x]
for y in range(len(Array[x])):
print Array[x][y]


If you don't actually need the index of each item, don't use for i in
range(), just iterate over the list:

for obj in Array:
print obj

Notice that your list has two items, the first is a string and the second
is a sub-list. The natural way of proceeding would be:

for obj in Array:
for item in obj:
print item

but that gives too much: it iterates over the string, giving you
individual characters.

Instead, do this:

for obj in Array:
if isinstance(obj, list):
for item in obj:
print item
else:
print obj


which helps, but not enough: it only prints two levels down, and your data
has three. This time -- next time it might have two, or fifteen, or one...

Instead, create a helper function like this:

def walk(seq):
"""Walk over a sequence of items, printing each one in turn, and
recursively walking over sub-sequences.
"""
print seq
if isinstance(seq, list):
for item in seq:
walk(item)


Notice that this function calls itself.

This version of walk() prints the entire sequence at every level. Here is
a version which doesn't:

def walk2(seq):
if isinstance(seq, list):
for item in seq:
walk2(item)
else:
print seq
 
M

Marc 'BlackJack' Rintsch

Steven said:
for obj in Array:
if isinstance(obj, list):
for item in obj:
print item
else:
print obj

I would "reverse" that check and test `obj` for not being a string::

for obj in Array:
if not isinstance(obj, basestring):
for item in obj:
print item
else:
print obj

This way it works with other types of iterables than lists too. Often
strings are the only type that one don't want to iterate over in such a
context.

Ciao,
Marc 'BlackJack' Rintsch
 

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

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top