Ian Lee
Ian Lee

Reputation: 11

Shuffle Program (list index out of range error)

I have built this program to take any number of lists of any size, and output a new list nlist where all individuals in the list have been sorted one after another in order from the first list to last. An example would be to input the lists [1,2,3,4] and [5,6,7,8] and output [1,5,2,6,3,7,4,8] creating a sort of shuffled type thing.

My reasoning for this code is that all lists to be shuffled would be individuals of a larger container list. The program starts with an if statement checking whether or not the container list contains anything. Then it runs through the x of the container list which are the lists to be shuffled. In this loop, it checks to see whether or not the list x contains any individuals and to remove that list if it does not. After that, it would add the first number of x to the new list and remove it from x. After it has done this it will recur so that it can do it again with the new x[0] until all of the lists are empty and all x[0] shuffled into the new list.

The problem is, when I run this it comes up with a list index out of range error. I assume this is because at the end of the program a number of x's end up being empty but the program registers the container list as being full because it contains these empty lists. It then removes them from the list and tries to run the rest of the program but can't because there is nothing to run it on. I believe this because it does end up printing out the shuffled list but still comes up with an error. I tried fixing this by adding a recursion after the list.remove(x) so that it could run the program again with the removed x.

Any ideas on how to solve this problem?

def shuffle(list, nlist):            #list is a list of lists to be shuffled
    if list:                         #checks for a completed task
        for x in list:               #runs through lists to be completed
            if not x:                #checks if a list is empty
                list.remove(x)       #if empty removes that list
                shuffle(list, nlist) #recurs the function
            nlist.append(x[0])       #adds 0 index of x to nlist
            x.remove(x[0])           #removes 0 index of x from x
        shuffle(list, nlist)         #recurs the function until task is complete
    else:
        print(nlist)                 #prints end result`enter code here`

Upvotes: 1

Views: 159

Answers (1)

pixie999
pixie999

Reputation: 498

The reason for the IndexError is that

In the code block

            if x == []:              #checks if a list is empty
                list.remove(x)       #if empty removes that list
                shuffle(list, nlist) #recurs the function
            nlist.append(x[0])       #adds 0 index of x to nlist
            x.remove(x[0])           #remo

while you are checking for an empty x, after the control returns from the shuffle(list, nlist) #recurs the function, nlist.append(x[0]) still gets called with an empty x(because it's in the same block of code) causing the error

To solve this(using your existing code), you can simple use an else condition to ensure that the block

nlist.append(x[0])       #adds 0 index of x to nlist
x.remove(x[0])  

does not execute if x is empty

Something along the lines of

def shuffle(list, nlist):            #list is a list of lists to be shuffled
    if list:                   #same as if list != []
        for x in list:               #runs through lists to be completed
            if not x:              #same is if x != []
                list.remove(x)       #if empty removes that list
                shuffle(list, nlist) #recurs the function
            else:
                nlist.append(x[0])       #adds 0 index of x to nlist
                x.remove(x[0])           #removes 0 index of x from x
                shuffle(list, nlist)         #recurs the function until task is complete
    else:                        
        print(nlist)

A nice way of implementing such a function would be using the zip function in python

import itertools


def shuffle(list, nlist):
    for values in itertools.izip_longest(*list):
        nlist.extend([value for value in values if value])
    del list

n= []
shuffle([[1,2,3], [4,5,6], []], n)
print n

Output:

[1, 4, 2, 5, 3, 6]

Explanation:

The zip function can take in multiple iterators (such as a list) and return a tuple with the next value from each of the iterators given. The built in zip function only iterates until the shortest iterator (the shortest list in this case). izip_longest iterates over the longest list and pads all missing values with your given choice(default:None)

A * before a structure in python expands it to all subvalues in the container For example if a = [1, 2, 3, 4] custom_func(1, 2, 3, 4) is same as custom_func(*a)

Now, since we are padding our extra values(due to differential sublist lengths) we need to only add the non None values to our final list

[value for value in values if value] takes the next tuple returned by the izip_longest(...) function and removes all None values from it while appending all the remaining ones to nlist

At the end, we can delete the list object after populating nlist

Upvotes: 1

Related Questions