Sorting without transitivity

Frank Niessink frank at niessink.com
Tue Apr 29 14:37:43 EDT 2003


On Sat Apr 19 23:34:05 2003, Frank Niessink wrote:
> Hi all,
> 
> [It's been while since I've dealt with transitivity and stuff, so
> I hope I got the terminology right]
> 
> I have objects that are not transitivily ordered, e.g.:
> 
> A > B
> A == C
> B == C
> 
> Now I have a list [A, B, C] and I want to sort it.
> The resulting list should have B before A, I don't care where
> C is. However, the Python list.sort() method (Python 2.2.2 on cygwin)
> doesn't put A and B in the right order.
> 
> How can I get the desired behavior? Should I implement my own
> sort algorithm? Any pointers?

Hi all,

First, thanks for all the help and sorry for not responding sooner.
I really appreciate the cheerful and supporting nature of this group.

I've looked into the existing topological sorting implementations in
Python, but all of them seemed to assume that the user of the method
already knows what items are smaller than which other items. 

In my case I don't have that information readily available, so I 
wanted the algorithm to take care of that. Also, giving an exception 
when there are cycles was not acceptable. 

So, I've been working on another implementation. Below is a tlist 
class that sorts its contents topologically. List items should 
provide a __lt__ method and an __eq__ method.

Any comments? Suggestions for improvements?

(Of course I have tests, mail me if you'd like to see the tests as well.)

---------- tlist.py --------------------

class tlist(list):
    ''' Topological list class. This class uses topological sort to
        sort its contents. List items should provide __lt__ and 
        __eq__ methods. '''
        
    def __init__(self, initial=None):
        list.__init__(self, initial or [])
        self.sort()

    def sort(self):
        result = []
        while self:
            result.append(self.popmin())
        self[:] = result

    def popmin(self):
        min = self.min()
        self.remove(min)
        return min

    def min(self):
        smallest, remainder = self[0], self[1:]
        found = False
        while not found:
            for item in remainder:
                if item < smallest:
                    remainder.remove(item)
                    smallest = item
                    break
            else:
                found = True
        return smallest

----------------------------------------

Thanks again, Frank

-- 
The Nutri-Matic was designed and manufactured by the Sirius Cybernetics 
Corporation whose complaints department now covers all the major land masses
of the first three planets in the Sirius Tau Star system.
	-- Douglas Adams, 'The Hitch Hiker's Guide to the Galaxy'





More information about the Python-list mailing list