1

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.globali = 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()
4
  • Any particular reason why you aren't using a Pythonic mechanism for sorting? Commented Mar 15, 2010 at 0:08
  • 2
    upvoting the question. Presenting bad code ≠ bad question! He also tagged it beginner, so he needs some kindness :) Commented Mar 15, 2010 at 0:19
  • It is part of an assignment for a python class. For bonus marks we can make our own class to preform sorting. Commented Mar 15, 2010 at 2:43
  • We name classes like FooBar, not foo_bar. Despite Python shipping with a few types not named like this, people pretty uniformly expect capitalized names for user-defined classes. Commented Mar 15, 2010 at 2:48

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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.

Comments

1

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.

2 Comments

Thanks I didn't realize that in this case = would point one variable at another. I'm making my own sort function for bonus marks on a python assignment.
@Protean, in a sensible course reinventing the wheel (using your own sort instead of Python's incredibly good one) should cost points!-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.