1

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`
Masoud Rahimi
  • 5,785
  • 15
  • 39
  • 67
Ian Lee
  • 11
  • 1
  • As a new programmer, I would avoid recursion for now. If you need to repeat something, just use a loop. This problem doesn't really need recursion. – Blorgbeard Feb 08 '19 at 07:27
  • Possible duplicate of [Interleave multiple lists of the same length in Python](https://stackoverflow.com/questions/7946798/interleave-multiple-lists-of-the-same-length-in-python) – Azat Ibrakov Feb 08 '19 at 07:27

1 Answers1

1

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

pixie999
  • 468
  • 5
  • 11
  • Yeah that worked. So what I got from this is that the program will continue to go through the rest of the code after an if statement unless this code is included in an else statement. Thank you very much. – Ian Lee Feb 08 '19 at 08:02
  • Yes, code will continue executing unless you use some form of a conditional or execution control statement such as break continue etc For example you could have added a continue at the end of your if block and you wouldn't need the else block. You are welcome. I have updated the answer with a cleaner and more pythonic implementation for your reference. Feel free to mark this solution accepted if it solved your problem :) – pixie999 Feb 08 '19 at 08:07