Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Most Pythonic way to iteratively build up a list? [closed]

Tags:

python

list

I was trying to do something in Python that uses the following general procedure, and I want to know what the best way to approch this is.

First, an initialization step:

  • Create an item M.
  • Create a list L and add M to L.

Second, loop through the following:

  • Create a new item by modifying the last item added to L.
  • Add the new item to L.

As a simple example, say I want to create a list of lists where the nth list contains the numbers from 1 to n. I could use the following (silly) procedure.

  • Initially M is [1] and L=[[1]].
  • Next, modify [1] by adding 2 to it to create the new item [1,2], then add [1,2] to L so L=[[1],[1,2]].
  • Next, modify [1,2] by adding 3 to it to create the new item [1,2,3], then add [1,2,3] to L so L=[[1],[1,2],[1,2,3]].
  • Next, modify [1,2,3] by adding 4 to it to create the new item [1,2,3,4], then add [1,2,3,4] to L so L=[[1],[1,2],[1,2,3],[1,2,3,4]]. etc.

I tried a few things, but most of them would modify not just the last item added but also items added to L in previous steps. For the particular problem I was interested in, I did manage to find a solution that behaves properly (at least for small cases), but it seems inelegant, I’m not sure why it works when other things didn’t, and I’m not even confident that it would still behave as desired for large cases. I’m also not confident that I could adapt my approach to similar problems. It's not a case of me not understanding the problem, since I've coded the same thing in other programming languages without issues.

So I’m wondering how more experienced Python programmers would handle this general task.

(I’m omitting my own code in part because I’m new here and I haven’t figured out how to enter it on stackoverflow, but also because it's long-ish and I don’t want help with the particular problem, but rather with how to handle the more general procedure I described above.)

like image 487
Randy E Avatar asked Aug 30 '14 23:08

Randy E


1 Answers

When adding a list object M to another list, you are only adding a reference; continuing to manipulate the list M means you will see those changes reflected through the other reference(s) too:

>>> M = []
>>> resultlist = []
>>> resultlist.append(M)
>>> M is resultlist[0]
True
>>> M.append(1)
>>> resultlist[0]
[1]
>>> M
[1]

Note that M is resultlist[0] is True; it is the same object.

You'd add a copy of M instead:

resultlist.append(M[:])

The whole slice here ([:] means to slice from start to end) creates a new list with a shallow copy of the contents of M.

The generic way to build produce a series L from a continuously altered starting point M is to use a generator function. Your simple add the next number to M series could be implemented as:

def growing_sequence():
    M = []
    counter = 0
    while True:
        M.append(counter)
        counter += 1
        yield M[:]

This will yield ever longer lists each time you iterate, on demand:

>>> gen = growing_sequence()
>>> next(gen)
[0]
>>> next(gen)
[0, 1]
>>> for i, lst in enumerate(gen):
...     print i, lst
...     if i == 2: break
...
0 [0, 1, 2]
1 [0, 1, 2, 3]
2 [0, 1, 2, 3, 4]
like image 113
Martijn Pieters Avatar answered Sep 30 '22 05:09

Martijn Pieters