Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I end a while loop with a for loop in it?

Im trying to create a sequence of jobs, and put them in an array. the coding works if I run the lines separately. The one problem is that it does not stop the while loop when count equals amountofmachines it gives the error:

IndexError: list assignment index out of range

Im a bit new to python and used to Matlab. How can I end this while loop and make the code resume at the line a.sort()? import random import numpy as np from random import randint

MachineNumber = 6 #amount of machines imported from Anylogic
JobNumber = 4 #amount of job sequences
JobSeqList = np.zeros((JobNumber,MachineNumber), dtype=np.int64)
amountofmachines = randint(1, MachineNumber) #dictated how much machines the order goes through
a = [0]*amountofmachines #initialize array of machines sequence
count = 0 #initialize array list of machines
element  = [n for n in range(1, MachineNumber+1)]

while count <= amountofmachines:
    a[count]  = random.choice(element)
    element.remove(a[count])
    count = count + 1

a.sort() #sorts the randomized sequence
A = np.asarray(a)       #make an array of the list
A = np.pad(A, (0,MachineNumber-len(a)), 'constant')     #adds zeros to the end of sequence
#add the sequence to the array of all sequences
JobSeqList[0,:] = A[:]
like image 862
Dhuijsman Avatar asked Jan 24 '23 04:01

Dhuijsman


2 Answers

I have tested your code, and found the answer!

Matlab indexes start at 1, so the first item in a list would be at 1..

However, python indexes start at 0, so the first item in a list would be at 0…

Change this line:

while count <= amountofmachines

To be:

while count < amountofmachines

Updated Code:


import random
import numpy as np

from random import randint

MachineNumber = 6 #amount of machines imported from Anylogic

JobNumber = 4 #amount of job sequences

JobSeqList = np.zeros((JobNumber,MachineNumber), dtype=np.int64)

amountofmachines = randint(1, MachineNumber) #dictated how much machines the order goes through

a = [0]*amountofmachines #initialize array of machines sequence

count = 0 #initialize array list of machines

element  = [n for n in range(1, MachineNumber+1)]

while count < amountofmachines:
    a[count]  = random.choice(element)
    element.remove(a[count])
    count = count + 1

a.sort() #sorts the randomized sequence

A = np.asarray(a)       #make an array of the list

A = np.pad(A, (0,MachineNumber-len(a)), 'constant')     #adds zeros to the end of sequence

#add the sequence to the array of all sequences

JobSeqList[0,:] = A[:]

like image 155
Samuel Avatar answered Feb 05 '23 21:02

Samuel


The problem with your while loop using < vs <= has already been answered, but I'd like to go a bit further and suggest that building a list in this way (by having a counter you increment or decrement manually) is something that's almost never done in Python in the first place, in the hope that giving you some more "pythonic" tools will help you avoid similar stumbling blocks in the future as you're getting used to Python. Python has really great tools for iterating over and building data structures that eliminate a lot of opportunities for minor errors like this, by taking all the "busy work" off of your shoulders.

All of this code:

a = [0]*amountofmachines #initialize array of machines sequence

count = 0 #initialize array list of machines

element  = [n for n in range(1, MachineNumber+1)]

while count < amountofmachines:
    a[count]  = random.choice(element)
    element.remove(a[count])
    count = count + 1

a.sort() #sorts the randomized sequence

amounts to "build a sorted array of amountofmachines unique numbers taken from range(1, MachineNumber+1)", which can be more simply expressed using random.sample and sorted:

a = sorted(random.sample(range(1, MachineNumber + 1), amountofmachines))

Note that a = sorted(a) is the same as a.sort() -- sorted does a sort and returns the result as a list, whereas sort does an in-place sort on an existing list. In the line of code above, random.sample returns a list of random elements taken from the range, and sorted returns a sorted version of that list, which is then assigned to a.

If random.sample didn't exist, you could use random.shuffle and a list slice. This of this as shuffling a deck of cards (element) and then taking amountofmachines cards off the top before re-sorting them:

element  = [n for n in range(1, MachineNumber+1)]
random.shuffle(element)
a = sorted(element[:amountofmachines])

If neither of those existed and you had to use random.choice to pick elements one by one, there are still easier ways to built a list through iteration; there's no need to statically pre-allocate the list, and there's no need to track your iteration with a counter you manage yourself, because for does that for you:

a = []
element  = [n for n in range(1, MachineNumber+1)]
for i in range(amountofmachines):
    a.append(random.choice(element))
    element.remove(a[i])
a.sort()

To make it simpler yet, it's not necessary to even have the for loop keep track of i for you, because you can access the last item in a list with [-1]:

a = []
element  = [n for n in range(1, MachineNumber+1)]
for _ in range(amountofmachines):
    a.append(random.choice(element))
    element.remove(a[-1])
a.sort()

and to make it simpler yet, you can use pop() instead of remove():

a = []
element  = [n for n in range(1, MachineNumber+1)]
for _ in range(amountofmachines):
    a.append(element.pop(random.choice(range(len(element)))))
a.sort()

which could also be expressed as a list comprehension:

element  = [n for n in range(1, MachineNumber+1)]
a = [
    element.pop(random.choice(range(len(element)))) 
    for _ in range(amountofmachines)
]
a.sort()

or as a generator expression passed as an argument to sorted:

element  = [n for n in range(1, MachineNumber+1)]
a = sorted(
    element.pop(random.choice(range(len(element)))) 
    for _ in range(amountofmachines)
)
like image 31
Samwise Avatar answered Feb 05 '23 20:02

Samwise