2

I'm using web.py to spin up endpoints and as such, I present a list of endpoints like so

urls = ('/(.*)', 'base', 
        '/shapes/(.*)', 'shapes', 
        '/sounds/(.*)', 'sounds', 
        '/shapes/rectangualar/(.*)', 'rectangualarShapes', 
        '/sounds/loud/(.*)', 'loudSounds')

As web.py will see the first one and match all possible endpoints to it, they need to be ordered, most specific first, i.e.

urls = ('/shapes/rectangualar/(.*)', 'rectangualarShapes', 
        '/shapes/(.*)', 'shapes',
        '/sounds/loud/(.*)', 'loudSounds' 
        '/shapes/(.*)', 'shapes', 
        '/sounds/(.*)', 'sounds',
        '/(.*)', 'base')

I want to order these, by URI. Firstly if there's a simple way to do it, as tuples, it would be great but I figure I need to convert them to objects

class Endpoint(object):
    def __init__(self, id, classname):
        self.id = id
        self.classname = classname

    def getId(item):
        return self.id

and print sorted(endpointList, key=id) them. How would I do this in Python 3+? I've come across comparator functions but it seems they are deprecated.

What is the best way to do custom sorting?

2 Answers 2

2
sorted(endpointList, key=lambda endpoint: endpoint.id)

or

sorted(endpointList, key=Endpoint.getId)

id is a builtin function that does something else which you don't want, hence your code not working.

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

4 Comments

there is also key=operator.attrgetter('id', 'classname')
This doesn't work, result:- [/(.*) -> 'base', /shapes/(.*) -> 'shapes', /shapes/rectangualar/(.*) -> 'rectangualarShapes', /sounds/(.*) -> 'sounds', /sounds/loud/(.*) -> 'loudSounds'] The less specific /(.*) url is still at the top of the list. Isn't sort just trying to do it alphabetically?
Sorry, I just saw key=id and jumped to that as a likely problem. Yes, it's alphabetical. I don't know how to order by specificity. But key functions are indeed the usual way to sort a list. If you can really only think of how to express this using a comparator function, check out functools.cmp_to_key.
the solution by @Ilja Everilä actually works well :)
1

Firstly if there's a simple way to do it, as tuples it would be great

Without wrapping in a custom object:

from itertools import chain
from operator import itemgetter

sorted_urls = tuple(chain.from_iterable(sorted(zip(urls[::2],
                                                   urls[1::2]),
                                               key=itemgetter(0), reverse=True)))

If using chain is not your thing, flatten with generator expressions:

tuple(x for pair in sorted(zip(urls[::2], urls[1::2]),
                           key=itemgetter(0), reverse=True)
      for x in pair)

5 Comments

Didn't try the first one but the second one works a treat. Now I need to get my head around how it works :P
It builds 2-tuples (path, name) with the zip() by stepping in increments of 2 from index 0 and 1, reverse sorts them according to path with itemgetter(0) (change the key as necessary) and flattens the result back to a tuple. The for ... for ... syntax for flattening is a bit nasty, as the innermost for is actually farthest away from the result expression.
What really confused me was how it manages to tell the difference between fine and coarse grained URLs and didn't just attempt an alphabetical sort.
Well it is just an alphabetical sort, just reversed. You could also sort with something like lambda pair: (len(pair[0]), pair[0]), which would sort them from longest to shortest, alphabetically, if reversed. All in all I guess the best thing would be to just have the configuration in the correct order to begin with :P
Really? That's strange because it seems to sort as expected by granularity. I'll need to make some more advanced tests. Sadly, my code has no way of knowing all tuple entries up front, as you can see... github.com/rossdrew/endpointSim.py

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.