Problem with for-loop in python
This code is supposed to be able to sort the items in self.array based upon the order of the characters in self.order. The method sort runs properly until the third iteration, unil for some reason the for loop seems to repeat indefinitely. What is going on here?
Edit: I'm making my own sort function because it is a bonus part of a python assignment I have.
class sorting_class:
def __init__(self):
self.array = ['ca', 'bd', 'ac', 'ab'] #An array of strings
self.arrayt = []
self.开发者_如何学JAVAglobali = 0
self.globalii = 0
self.order = ['a', 'b', 'c', 'd'] #Order of characters
self.orderi = 0
self.carry = []
self.leave = []
self.sortedlist = []
def sort(self):
for arrayi in self.arrayt: #This should only loop for the number items in self.arrayt. However, the third time this is run it seems to loop indefinitely.
print ('run', arrayi) #Shows the problem
if self.order[self.orderi] == arrayi[self.globali]:
self.carry.append(arrayi)
else:
if self.globali != 0:
self.leave.append(arrayi)
def srt(self):
self.arrayt = self.array
my.sort() #First this runs the first time.
while len(self.sortedlist) != len(self.array):
if len(self.carry) == 1:
self.sortedlist.append(self.carry)
self.arrayt = self.leave
self.leave = []
self.carry = []
self.globali = 1
self.orderi = 0
my.sort()
elif len(self.carry) == 0:
if len(self.leave) != 0: #Because nothing matches 'aa' during the second iteration, this code runs the third time"
self.arrayt = self.leave
self.globali = 1
self.orderi += 1
my.sort()
else:
self.arrayt = self.array
self.globalii += 1
self.orderi = self.globalii
self.globali = 0
my.sort()
self.orderi = 0
else: #This is what runs the second time.
self.arrayt = self.carry
self.carry = []
self.globali += 1
my.sort()
my = sorting_class()
my.srt()
The key-extractor Alex mentions is trivial enough to put in a lambda function
>>> array = ['ca', 'bd', 'ac', 'ab']
>>> order = ['a', 'b', 'c', 'd']
>>> sorted(array, key=lambda v:map(order.index,v))
['ab', 'ac', 'bd', 'ca']
>>> order = ['b', 'a', 'c', 'd']
>>> sorted(array, key=lambda v:map(order.index,v))
['bd', 'ab', 'ac', 'ca']
>>> order = ['d', 'c', 'b', 'a']
>>> sorted(array, key=lambda v:map(order.index,v))
['ca', 'bd', 'ac', 'ab']
Let's see how this works:
map
calls the method order.index
for each item in v
and uses those return values to create a list.
v
will be one of the elements of array
>>> order = ['a', 'b', 'c', 'd']
>>> map(order.index,array[0])
[2, 0]
>>> map(order.index,array[1])
[1, 3]
>>> map(order.index,array[2])
[0, 2]
>>> map(order.index,array[3])
[0, 1]
The function is supplied as a key=
to sort, so internally those lists are being sorted instead of the strings.
During the third pass of your loop you are appending new elements to the list you are iterating over therefore you can never leave the loop:
self.arrayt = self.leave
- this assignment leads to the fact that self.leave.append(arrayi)
will append elements to the list self.arrayt
refers to.
In general you may think about creating copies of lists not just assigning different variables/members to the same list instances.
You have self.arrayt = self.leave
which makes arrayt
refer to exactly the same array as leave
(it's not a copy of the contents!!!), then in the loop for arrayi in self.arrayt:
you perpetrate a self.leave.append(arrayi)
-- which lenghtens self.leave
, which is just another name for the very list self.arrayt
you're looping on. Appending to the list you're looping on is a good recipe for infinite loops.
This is just one symptom of this code's inextricable messiness. I recommend you do your sorting with the built-in sort
method and put your energy into defining the right key=
key-extractor function to get things sorted the exact way you want -- a much more productive use of your time.
精彩评论