473,563 Members | 2,667 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Sorting on multiple values, some ascending, some descending

I have successfully used the sort lambda construct described in
http://mail.python.org/pipermail/pyt...il/377443.html.
However, how do I take it one step further such that some values can be
sorted ascending and others descending? Easy enough if the sort values
are numeric (just negate the value), but what about text?

Is the only option to define an external sorting function to loop
through the list and perform the comparisons one value at a time?

Jan 3 '07 #1
11 18276

dwelden wrote:
I have successfully used the sort lambda construct described in
http://mail.python.org/pipermail/pyt...il/377443.html.
However, how do I take it one step further such that some values can be
sorted ascending and others descending? Easy enough if the sort values
are numeric (just negate the value), but what about text?

Is the only option to define an external sorting function to loop
through the list and perform the comparisons one value at a time?
The simplest way is to take advantage of sort-stability and do
successive sorts. For example, to sort by a primary key ascending and
a secondary key decending:

L.sort(key=lamb da r: r.secondary, reverse=True)
L.sort(key=lamb da r: r.primary)

A less general technique is to transform fields in a way that reverses
their comparison order:

L.sort(key=lamb da r: (-r.age, r.height)) # sorts descending age
and ascending height
Raymond

Jan 3 '07 #2
On Wed, 2007-01-03 at 10:48 -0800, dwelden wrote:
I have successfully used the sort lambda construct described in
http://mail.python.org/pipermail/pyt...il/377443.html.
However, how do I take it one step further such that some values can be
sorted ascending and others descending? Easy enough if the sort values
are numeric (just negate the value), but what about text?

Is the only option to define an external sorting function to loop
through the list and perform the comparisons one value at a time?
If by "external sorting function" you mean a custom comparison function
to pass to sort as the cmp argument, then that's one option, but not the
only one.

If you know in advance which columns contain strings, you could write a
function that operates on strings and is strictly monotonically
decreasing, i.e. it behaves such that f(x) < f(y) if and only if x y.
This function could then be used in the sort key for sorting on a string
column in descending order. The following function does the trick:

def antistring(x):
return [256-ord(c) for c in x]+[257]

(Proof by vigorous handwaving.)

Lastly, if your array is small enough that you can tolerate the
performance hit of multiple passes, you could exploit the fact that
sort() is guaranteed to be stable in sufficiently recent releases of
CPython. Split your sort on n columns into n separate sorts on a single
column each, and use the 'reverse' parameter to specify whether to sort
forward or backwards.

Hope this helps,

Carsten.
Jan 3 '07 #3
Raymond Hettinger:
The simplest way is to take advantage of sort-stability and do
successive sorts. For example, to sort by a primary key ascending and
a secondary key decending:
L.sort(key=lamb da r: r.secondary, reverse=True)
L.sort(key=lamb da r: r.primary)
That's probably the faster and simpler way.
The following solution is probably slow, memory-hungry, and it's not
tested much so it may be buggy too, but it shows my idea, and bugs can
be fixed:

class Inverter:
def __init__(self, item, reversed=False) :
self.item = item
self.reversed = reversed
def __cmp__(self, other):
if self.reversed:
return cmp(other.item, self.item)
else:
return cmp(self.item, other.item)

data = [[1, "a", "b"], [1, "b", "d"], [1, "d", "a"]]
reverses = [True, False, False]

print sorted(data, key=lambda subseq: map(Inverter, subseq, reverses))

Bye,
bearophile

Jan 3 '07 #4
Raymond Hettinger wrote:
dwelden wrote:
>I have successfully used the sort lambda construct described in
http://mail.python.org/pipermail/pyt...il/377443.html.
However, how do I take it one step further such that some values can be
sorted ascending and others descending? Easy enough if the sort values
are numeric (just negate the value), but what about text?

Is the only option to define an external sorting function to loop
through the list and perform the comparisons one value at a time?

The simplest way is to take advantage of sort-stability and do
successive sorts. For example, to sort by a primary key ascending and
a secondary key decending:

L.sort(key=lamb da r: r.secondary, reverse=True)
L.sort(key=lamb da r: r.primary)

A less general technique is to transform fields in a way that reverses
their comparison order:

L.sort(key=lamb da r: (-r.age, r.height)) # sorts descending age
and ascending height
You can get generality if you are willing to pay the performance penalty:
>>items
[(3, 1), (2, 2), (1, 1), (1, 3), (2, 1), (2, 3), (1, 2)]
>>class Reverse:
.... def __cmp__(self, other):
.... return -cmp(self.value, other.value)
.... def __init__(self, value):
.... self.value = value
....
>>items.sort(ke y=lambda (x, y): (x, Reverse(y)))
items
[(1, 3), (1, 2), (1, 1), (2, 3), (2, 2), (2, 1), (3, 1)]

Peter
Jan 3 '07 #5
dwelden wrote:
I have successfully used the sort lambda construct described in
http://mail.python.org/pipermail/pyt...il/377443.html.
However, how do I take it one step further such that some values can be
sorted ascending and others descending? Easy enough if the sort values
are numeric (just negate the value), but what about text?
You got already some good replies; here's yet another less-than-optimal
way:

class revstr(str):
def __lt__(self, other):
return str.__gt__(self ,other)
def __gt__(self, other):
return str.__lt__(self ,other)

L.sort(key=lamb da i: (i.somestring, revstr(i.someot herstring),
i.anotherkey))
George

Jan 3 '07 #6
The simplest way is to take advantage of sort-stability and do
successive sorts. For example, to sort by a primary key ascending and
a secondary key decending:

L.sort(key=lamb da r: r.secondary, reverse=True)
L.sort(key=lamb da r: r.primary)
Excellent! That looks just like what I needed.
A less general technique is to transform fields in a way that reverses
their comparison order:

L.sort(key=lamb da r: (-r.age, r.height)) # sorts descending age
and ascending height
This one I had figured out, but could not see how to get it to work for
strings.

Much obliged.

Jan 3 '07 #7
dwelden wrote:
L.sort(key=lamb da r: r.secondary, reverse=True)
L.sort(key=lamb da r: r.primary)
Excellent! That looks just like what I needed.
Note that there is the (probably little used) operator.attrge tter()
too, with that you can avoid the possibly slow lambda:
L.sort(key=attr getter("primary ")

operator.itemge tter(n) is when you have items that can be be accessed
by index.

Bye,
bearophile

Jan 4 '07 #8
be************@ lycos.com a écrit :
Raymond Hettinger:
>The simplest way is to take advantage of sort-stability and do
successive sorts. For example, to sort by a primary key ascending and
a secondary key decending:
L.sort(key=lamb da r: r.secondary, reverse=True)
L.sort(key=lamb da r: r.primary)

That's probably the faster and simpler way.
The following solution is probably slow, memory-hungry, and it's not
tested much so it may be buggy too, but it shows my idea, and bugs can
be fixed:

class Inverter:
def __init__(self, item, reversed=False) :
self.item = item
self.reversed = reversed
def __cmp__(self, other):
if self.reversed:
return cmp(other.item, self.item)
else:
return cmp(self.item, other.item)

data = [[1, "a", "b"], [1, "b", "d"], [1, "d", "a"]]
reverses = [True, False, False]

print sorted(data, key=lambda subseq: map(Inverter, subseq, reverses))
Nice trick, but don't get too caught up using classes ;) Try that one
instead for much better performance :

class Inverter:
def __init__(self, item):
self.item = item
def __cmp__(self, other):
return cmp(other, self.item)

def invert_if(item, reversed=False) :
if reversed:
return Inverter(item)
return item

data = [[1, "a", "b"], [1, "b", "d"], [1, "d", "a"]]
reverses = [True, False, False]

print sorted(data, key=lambda subseq: map(invert_, subseq, reverses))
Jan 4 '07 #9
On 2007-01-03, dwelden <dw*****@gmail. comwrote:
I have successfully used the sort lambda construct described in
http://mail.python.org/pipermail/pyt...il/377443.html.
However, how do I take it one step further such that some
values can be sorted ascending and others descending? Easy
enough if the sort values are numeric (just negate the value),
but what about text?

Is the only option to define an external sorting function to
loop through the list and perform the comparisons one value at
a time?
Another trick is to factor the key application out of the sort.
This may be a good idea if when you want to minimize the number
of times your key function is called.

The idea is to mangle the list temporarily so you can use an
unkeyed sort, and then unmangle the sorted data. Here's a silly
example using a phone directory that's not stored in a format
that's easy to sort.
>>a = [("Neil Cerutti", "8025552954 "), ("Ted Smith", "8025552281 "), ("Barny Fife", "8025551105 ")]
b = [(" ".join(reversed (x.split())), y) for (x, y) in a]
b
[('Cerutti Neil', '8025552954'), ('Smith Ted', '8025552281'), ('Fife Barny', '8025551105')]
>>b.sort()
b
[('Cerutti Neil', '8025552954'), ('Fife Barny', '8025551105'), ('Smith Ted', '8025552281')]
>>a = [(" ".join(reversed (x.split())), y) for (x, y) in b]
a
[('Neil Cerutti', '8025552954'), ('Barny Fife', '8025551105'), ('Ted Smith', '8025552281')]

--
Neil Cerutti
Eddie Robinson is about one word: winning and losing. --Eddie Robinson's agent
Paul Collier
Jan 4 '07 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
2241
by: Henri Schomaecker | last post by:
Hi folks, does php 5 have a problem with html select lists which allow to choose multiple items? Whatever I tried I just can't get another or more than the last item selected in the list. Even if I select multiple items, a print_r($_POST) just shows the last selected item, and not a array of all selected values.
17
43901
by: Roland Hall | last post by:
Is there a way to return multiple values from a function without using an array? Would a dictionary object work better? -- Roland Hall /* This information is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose. */ Technet Script...
5
2241
by: Homer Simpson | last post by:
Hi All, I'm trying to write a method where I pass three arguments and the method returns six values. All the values will be doubles. First, is it possible to get multiple values returned by a method? Second, how do I do it? I know how to write the method, pass arguments to it and get a single value returned but how do I pass multiple values...
1
5749
by: Mark | last post by:
Rather than have only one column sorted in a single direction in a listview. I would like to be able to sort on any column in alternating directions (ascending,descending) eg. First column click sorts ascending and second sorts decending etc. Can anyone point me in a direction? Thanks, Mark
16
17384
by: Nikolay Petrov | last post by:
How can I return multiple values from a custom function? TIA
7
3714
by: pt36 | last post by:
Hi I have a php string like this: $string = "one two three four five" I have to sorting the values randomly every time the page are loaded. So, for example: first time "one two three four five" second time "three five one four two" third time
1
2191
by: wendy184 | last post by:
I'm used to using 2007 which allows multiple values in the lookup wizard, this helps hugely with my queries as the database i'm building has information on one parent who may have up to 5 kids. Now i'm building up a similar database in 2000 and could really use some help, 2000 won't allow multiple values in a lookup field which means if I have...
2
3662
ADezii
by: ADezii | last post by:
The incentive for this Tip was an Article by the amazing Allen Browne - I considered it noteworthy enough to post as The Tip of the Week in this Access Forum. Original Article by Allen Browne Traditionally, one has always thought that Functions can only return a single value, and for the most part that was true. Ever since Access 95, we...
2
2169
by: satyanarayan sahoo | last post by:
Can we write a method which returns multiple values?
0
3082
by: Maric Michaud | last post by:
Le Thursday 28 August 2008 03:43:16 norseman, vous avez écrit : Disctionaries are hash tables with a unique key and constant time lookup. What you want could be implemented as a complex data structures with as many dict as needed keys, but it seems you really want a relational table and a rdbms. This is exactly what they are for. A...
0
7659
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7882
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
8103
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
7634
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
1
5481
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
5208
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3634
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
1
2079
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
1194
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.