Reputation: 11
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
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