Search code examples
pythonlistparsingindexoutofrangeexceptionindex-error

Python puzzle: partitions of lists: Why is the index out of range?


Edited:

General problem: Using the elements of some list of length m*n, create a list with m sub-lists, each of length n.

In my case, m > n, and are 10 and 3 respectively.


The final output should be a list ("lis1") containing ten lists (the iterations of "nulis") with three elements each. Also, my current algorithm should leave "lis0" empty. The error is returned right at the last step.


I am parsing some CSV files (four columns - one with a list of 3 numbers, three with one number each about the respective lists) I generated using the CSV module. I couldn't figure out how to do this more elegantly reading the module's documentation and am having some trouble with the last step: recombining the terms in the list-columns into 3-element-long lists (the other columns are done).

The solution/explanation would be ideal, but I'll take an alternative approach if you've got one.

I can't remember some of the others, but I had tried using "for j in list: while (j == list[list.index(j)+1]) or (j == list[list.index(j)-1]): newlist.append(j)" but got memory errors. Solution for that would be sweet though not as pertinent because it would only work for a special case of what I'm looking into (one which works because of an inadequacy in another script I was writing). In the current version, I have tried to 'break' (concludes a step early but there's an overlooked error of the same type), 'continue', and 'pass', to no avail.


edited script into a function which gives the same error, feel free to give the special case (i.e. any solution to the problem outlined above with m=10, n=3)

def lispart(lis,length,depth):
    l0 = list(lis)
    l1 = []
    if ((len(l0)%length) != 0) or ((len(l0)%depth) != 0):
        return "Parity Error: length and/or depth do not correspond to list"
    else:
        for i in range(int(len(l0)/depth)):
            for j in range(depth):
                nulis = [l0[j] for j in range(depth)]
                l1.append(nulis)
                for k in nulis:
                    if k in l0:
                        l0.remove(l0[l0.index(k)])
print(lispart([i for i in range(30)], 10, 3))

I think the problem is due to there not being enough elements left to finish making new lists with. Ultimately, when you run it as I have it written out the last non-empty "lis0" printed statement is a list with just one number, namely the last element of the original list (which, fyi, had thirty elements). The last "lis1" print had 9 elements, and the next (last "nulis") element is correctly formulated but I can't tell if it gets appended because there winds up being an error before anything else is printed.

Traceback (most recent call last):
  File "script.py", line X, in <module>
    nulis = [lis0[j] for j in range(3)]
  File "script.py", line X, in <listcomp>
    nulis = [lis0[j] for j in range(3)]
IndexError: list index out of range

Any help would be gorgeous, folks!


Solution

  • Devised by David C. Ullrich and Peter Foreman from stack exchange maths:

    def lispart(lis,depth):
        lish = list(lis)
        assert(len(lish)%depth == 0)
        return [lish[j*depth:(j+1)*depth] for j in range((int(len(lish)/depth)))]