Iterating through a nested list

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • CamelR

    #1

    Iterating through a nested list

    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[i]
    for x in range(len(Array[i])):
    print Array[i][x]
    for y in range(len(Array[i][x])):
    print Array[i][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!

  • Steven D'Aprano

    #2
    Re: Iterating through a nested list

    On Sat, 15 Apr 2006 22:36:17 -0500, CamelR wrote:
    [color=blue]
    > 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[i]
    > for x in range(len(Array[i])):
    > print Array[i][x]
    > for y in range(len(Array[i][x])):
    > print Array[i][x][y][/color]

    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


    --
    Steven.

    Comment

    • Marc 'BlackJack' Rintsch

      #3
      Re: Iterating through a nested list

      In <pan.2006.04.16 .04.34.55.39513 7@REMOVETHIScyb er.com.au>, Steven
      D'Aprano wrote:
      [color=blue]
      > for obj in Array:
      > if isinstance(obj, list):
      > for item in obj:
      > print item
      > else:
      > print obj[/color]

      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

      Comment

      Working...