473,805 Members | 2,074 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

sorting list of complex numbers

The thread on sorting in Python 3 got me to thinking. How could I sort a
list of complex numbers using key?
>>lst = [random.random() +random.random( )*1j for i in range(10)]
lst
[(0.326722518499 59244+0.4142898 3433288791j), (0.352380564846 09881+0.9275820 3977208264j), (0.193378240381 25528+0.1652728 5180541951j), (0.475693071145 25849+0.7238196 0418815128j), (0.214988131350 82351+0.2046308 266222292j), (0.301427457569 37939+0.3521675 1451102601j), (0.773556763869 39132+0.0023447 924287695043j), (0.254773612460 6309+0.52234837 788936905j), (0.383491890813 50132+0.6201761 7694427096j), (0.583620967735 61245+0.8770244 3273108477j)]

As expected:
>>sorted(lst)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: no ordering relation is defined for complex numbers

This works:
>>sorted(lst, key=lambda x: x.real)
[(0.193378240381 25528+0.1652728 5180541951j), (0.214988131350 82351+0.2046308 266222292j), (0.254773612460 6309+0.52234837 788936905j), (0.301427457569 37939+0.3521675 1451102601j), (0.326722518499 59244+0.4142898 3433288791j), (0.352380564846 09881+0.9275820 3977208264j), (0.383491890813 50132+0.6201761 7694427096j), (0.475693071145 25849+0.7238196 0418815128j), (0.583620967735 61245+0.8770244 3273108477j), (0.773556763869 39132+0.0023447 924287695043j)]

but what if I want to sort by real, then imaginary parts? Here's a longer
list with 20 elements where there are only 10 distinct reals but 20 distinct
imaginaries:
>>pprint.pprint (lst)
[(1+2.73j),
(9+3.77j),
(7+27j),
(8+28j),
(2+2.8600000000 000003j),
(4+3.1200000000 000001j),
(2+22j),
(9+29j),
(3+2.9900000000 000002j),
(6+26j),
2.6000000000000 001j,
(8+3.6400000000 000001j),
(3+23j),
(5+3.25j),
(1+21j),
(5+25j),
20j,
(6+3.3799999999 999999j),
(7+3.5100000000 000002j),
(4+24j)]

I can sort by the real parts just fine:
>>lst.sort(key= lambda x: x.real)
pprint.pprint (lst)
[2.6000000000000 001j,
20j,
(1+2.73j),
(1+21j),
(2+2.8600000000 000003j),
(2+22j),
(3+2.9900000000 000002j),
(3+23j),
(4+3.1200000000 000001j),
(4+24j),
(5+3.25j),
(5+25j),
(6+26j),
(6+3.3799999999 999999j),
(7+27j),
(7+3.5100000000 000002j),
(8+28j),
(8+3.6400000000 000001j),
(9+3.77j),
(9+29j)]

but how do I then do a secondary sort by the imaginary part, preserving the
existing ordering on the real parts? Seems like I have to resort to a
Schwartzian transform and map the complex numbers to tuples, sort that, then
map them back. With the cmp key it would have been a fairly trivial task to
define the desired compare-real-then-imag function.

Is there a way to do this using just the key arg, no extra data structures?

Skip
Nov 9 '08 #1
16 9876
sk**@pobox.com wrote:
I can sort by the real parts just fine:
>>lst.sort(key= lambda x: x.real)
>>pprint.pprint (lst)
[2.6000000000000 001j,
20j,
(1+2.73j),
(1+21j),
(2+2.8600000000 000003j),
(2+22j),
(3+2.9900000000 000002j),
(3+23j),
(4+3.1200000000 000001j),
(4+24j),
(5+3.25j),
(5+25j),
(6+26j),
(6+3.3799999999 999999j),
(7+27j),
(7+3.5100000000 000002j),
(8+28j),
(8+3.6400000000 000001j),
(9+3.77j),
(9+29j)]

but how do I then do a secondary sort by the imaginary part, preserving the
existing ordering on the real parts? Seems like I have to resort to a
Schwartzian transform and map the complex numbers to tuples, sort that, then
map them back. With the cmp key it would have been a fairly trivial task to
define the desired compare-real-then-imag function.

Is there a way to do this using just the key arg, no extra data structures?
Is a tuple an extra data structure?
>>lst.sort(key= lambda x: (x.real,x.imag) )
pprint.pprint (lst)
[2.6000000000000 001j,
20j,
(1+2.73j),
(1+21j),
(2+2.8600000000 000003j),
(2+22j),
(3+2.9900000000 000002j),
(3+23j),
(4+3.1200000000 000001j),
(4+24j),
(5+3.25j),
(5+25j),
(6+3.3799999999 999999j),
(6+26j),
(7+3.5100000000 000002j),
(7+27j),
(8+3.6400000000 000001j),
(8+28j),
(9+3.77j),
(9+29j)]

If you don't like the tuple then just do the two sorts separately:
>>lst.sort(key= lambda x: x.imag)
lst.sort(key= lambda x: x.real)
pprint.pprint (lst)
[2.6000000000000 001j,
20j,
(1+2.73j),
(1+21j),
(2+2.8600000000 000003j),
(2+22j),
(3+2.9900000000 000002j),
(3+23j),
(4+3.1200000000 000001j),
(4+24j),
(5+3.25j),
(5+25j),
(6+3.3799999999 999999j),
(6+26j),
(7+3.5100000000 000002j),
(7+27j),
(8+3.6400000000 000001j),
(8+28j),
(9+3.77j),
(9+29j)]
>>>
Nov 9 '08 #2
sk**@pobox.com schrieb:
The thread on sorting in Python 3 got me to thinking. How could I sort a
list of complex numbers using key?
>>lst = [random.random() +random.random( )*1j for i in range(10)]
>>lst
[(0.326722518499 59244+0.4142898 3433288791j), (0.352380564846 09881+0.9275820 3977208264j), (0.193378240381 25528+0.1652728 5180541951j), (0.475693071145 25849+0.7238196 0418815128j), (0.214988131350 82351+0.2046308 266222292j), (0.301427457569 37939+0.3521675 1451102601j), (0.773556763869 39132+0.0023447 924287695043j), (0.254773612460 6309+0.52234837 788936905j), (0.383491890813 50132+0.6201761 7694427096j), (0.583620967735 61245+0.8770244 3273108477j)]

As expected:
>>sorted(lst)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: no ordering relation is defined for complex numbers

This works:
>>sorted(lst, key=lambda x: x.real)
[(0.193378240381 25528+0.1652728 5180541951j), (0.214988131350 82351+0.2046308 266222292j), (0.254773612460 6309+0.52234837 788936905j), (0.301427457569 37939+0.3521675 1451102601j), (0.326722518499 59244+0.4142898 3433288791j), (0.352380564846 09881+0.9275820 3977208264j), (0.383491890813 50132+0.6201761 7694427096j), (0.475693071145 25849+0.7238196 0418815128j), (0.583620967735 61245+0.8770244 3273108477j), (0.773556763869 39132+0.0023447 924287695043j)]

but what if I want to sort by real, then imaginary parts? Here's a longer
list with 20 elements where there are only 10 distinct reals but 20 distinct
imaginaries:
>>pprint.pprint (lst)
[(1+2.73j),
(9+3.77j),
(7+27j),
(8+28j),
(2+2.8600000000 000003j),
(4+3.1200000000 000001j),
(2+22j),
(9+29j),
(3+2.9900000000 000002j),
(6+26j),
2.6000000000000 001j,
(8+3.6400000000 000001j),
(3+23j),
(5+3.25j),
(1+21j),
(5+25j),
20j,
(6+3.3799999999 999999j),
(7+3.5100000000 000002j),
(4+24j)]

I can sort by the real parts just fine:
>>lst.sort(key= lambda x: x.real)
>>pprint.pprint (lst)
[2.6000000000000 001j,
20j,
(1+2.73j),
(1+21j),
(2+2.8600000000 000003j),
(2+22j),
(3+2.9900000000 000002j),
(3+23j),
(4+3.1200000000 000001j),
(4+24j),
(5+3.25j),
(5+25j),
(6+26j),
(6+3.3799999999 999999j),
(7+27j),
(7+3.5100000000 000002j),
(8+28j),
(8+3.6400000000 000001j),
(9+3.77j),
(9+29j)]

but how do I then do a secondary sort by the imaginary part, preserving the
existing ordering on the real parts? Seems like I have to resort to a
Schwartzian transform and map the complex numbers to tuples, sort that, then
map them back. With the cmp key it would have been a fairly trivial task to
define the desired compare-real-then-imag function.

Is there a way to do this using just the key arg, no extra data structures?
Doesn't (untested)

key=lambda x: (x.real, x.imag)

work?

Diez
Nov 9 '08 #3
>Timeit suggests the single sort returning the real, imag tuples is
faster than two sorts each on one field, as you might expect since
many fewer calls to the key function are made.
SteveOnly half the number, of course. The advantage of the key
Stevefunction is that each element requires only one call out to a
StevePython function, and the comparisons then take place using a
SteveC-coded comparison function.

SteveBut you knew that already, right?

I knew about the C comparison function, not about the number of key calls.
I sort of assumed the key function was called whenever necessary since it
could have side effects. I confirmed that the key function is called once
per element instead of once per comparison.

Thanks,

Skip

Nov 10 '08 #4
Thomas Bellman wrote:
Steve Holden <st***@holdenwe b.comwrote:
>Only half the number, of course. The advantage of the key function is
that each element requires only one call out to a Python function, and
the comparisons then take place using a C-coded comparison function.

You don't need any Python-coded function at all. The operator
module is your friend: key=operator.at trgetter('real' , 'imag')
will create the required tuples for sorting.
True; "requires only one call out to the key function", then. You're
right, attrgetter will be faster still, and it's a really neat solution.

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC http://www.holdenweb.com/

Nov 12 '08 #5
Duncan Booth <du**********@i nvalid.invalidw rites:
If you don't like the tuple then just do the two sorts separately:
>lst.sort(key=l ambda x: x.imag)
lst.sort(key=l ambda x: x.real)
pprint.pprint( lst)
That only goes so far though. Suppose instead of complex numbers
you want to sort expressions, like:

a(b,c(d,e),f(g, h))

treat those as parse trees in the obvious way. You want to compare on
the root, and if the roots are equal, compare the left subtree, then
the right subtree, etc. Do you REALLY want to sort over and over
all the way to the max depth of all the trees?

I don't understand what the purpose of was of getting rid of the cmp
arg. It just seems to gratuitously make code hard to write.

Another thing that apparently broke was tuple destructuring in
function args. You can no longer say

def first((a,b)): return a
def second((a,b)): return b

make getters for the first and second elements of a tuple. Sure, you
could use operator.itemge tter for that example, but often you want to
parse out more complicated nested tuples. I do that all the time with
Python 2.5 (typically in conjunction with itertools.group by) but
if/when I downgrade to 3.0, a bunch of my code is going to break.
Nov 18 '08 #6
sk**@pobox.com writes:
but how do I then do a secondary sort by the imaginary part,...
Is there a way to do this using just the key arg, no extra data structures?
Clever solutions involving multiple sorts aside, I think what they
really want you to do is something like (untested):

class mkKey(complex):
def __lt__(self, other):
a = cmp(self.real, other.real)
return a if a else cmp(self.imag, other.imag)

then:

yourlist.sort(k ey=mkKey)

for fancier structures you'd need a full blown class implementation
with an init method. Either way you end up temporarily allocating a
lot of extra structures, but at least they're not all in memory
simultaneously like in the DSU pattern.
Nov 18 '08 #7
En Tue, 18 Nov 2008 08:41:58 -0200, Paul Rubin
<"http://phr.cx"@nospam. invalidescribió :
sk**@pobox.com writes:
>but how do I then do a secondary sort by the imaginary part,...
Is there a way to do this using just the key arg, no extra data
structures?

Clever solutions involving multiple sorts aside, I think what they
really want you to do is something like (untested):

class mkKey(complex):
def __lt__(self, other):
a = cmp(self.real, other.real)
return a if a else cmp(self.imag, other.imag)

then:

yourlist.sort(k ey=mkKey)

for fancier structures you'd need a full blown class implementation
with an init method. Either way you end up temporarily allocating a
lot of extra structures, but at least they're not all in memory
simultaneously like in the DSU pattern.
Yes, the keys for all items in the list are all created when the sort
begins, and live until the sort finishes. list.sort(key=. ..) is actually
implemented using the DSU pattern, something like this:

for i in range(len(alist )):
alist[i] = (key(alist[i]), alist[i])
# ...sort items...
for i in range(len(alist )):
alist[i] = alist[i][1]

except a custom `sortwrapper` object is used instead of a 2-item tuple.

--
Gabriel Genellina

Nov 18 '08 #8
Paul Rubin <http://ph****@NOSPAM.i nvalidwrites:
for fancier structures you'd need a full blown class implementation
with an init method. Either way you end up temporarily allocating a
lot of extra structures, but at least they're not all in memory
simultaneously like in the DSU pattern.
The implementation of python sort uses the DSU patterns.

--
Arnaud
Nov 18 '08 #9
Paul Rubin wrote:
That only goes so far though. Suppose instead of complex numbers
you want to sort expressions, like:

a(b,c(d,e),f(g, h))

treat those as parse trees in the obvious way.
Presuming that a, c, and f are function calls that return Tree
instances, you give Tree a __lt__ member that does what you say below.
You want to compare on
the root, and if the roots are equal, compare the left subtree, then
the right subtree, etc.
Do you REALLY want to sort over and over
all the way to the max depth of all the trees?
Don't understand this.
I don't understand what the purpose of was of getting rid of the cmp
arg.
Cmp requires a 3-way classification. Sorting only requires 2-way.
cmp was called nlogn times, key n times.
cmp in practical use amounted to calling some key function on both
items, so cmp amounted to 2*n*log(n) key calls pluse extra overhead.
Another thing that apparently broke was tuple destructuring in
function args. You can no longer say

def first((a,b)): return a
def second((a,b)): return b

make getters for the first and second elements of a tuple. Sure, you
could use operator.itemge tter for that example, but often you want to
parse out more complicated nested tuples. I do that all the time with
Python 2.5 (typically in conjunction with itertools.group by) but
if/when I downgrade to 3.0, a bunch of my code is going to break.
Do your tuple destructuring in the first statement in your body and
nothing will break. Don't upgrade until it is an upgrade for *you*.

Nov 18 '08 #10

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

Similar topics

5
1565
by: jwsacksteder | last post by:
I have a need to sort a list of elements that represent sections of a document in dot-separated notation. The built in sort does the wrong thing. This seems a rather complex problem and I was hoping someone smarter than me had already worked out the best way to approach this. For example, consider the following list- >>> foo >>> foo.sort() >>> foo
7
3270
by: Federico G. Babelis | last post by:
Hi All: I have this line of code, but the syntax check in VB.NET 2003 and also in VB.NET 2005 Beta 2 shows as unknown: Dim local4 As Byte Fixed(local4 = AddressOf dest(offset)) CType(local4, Short) = CType(src, Short)
20
4088
by: Xah Lee | last post by:
Sort a List Xah Lee, 200510 In this page, we show how to sort a list in Python & Perl and also discuss some math of sort. To sort a list in Python, use the “sort†method. For example: li=;
7
10088
by: Foodbank | last post by:
Hi everyone. I'm having trouble with this radix sorting program. I've gotten some of it coded except for the actual sorting :( The book I'm teaching myself with (Data Structures Using C and C++) just doesn't explain things good at all and the tutorials I've viewed don't really explain least significant digit first sorting or show examples, which would be most helpful. I've commented the section where I know that the iteration of the...
16
2769
by: Kittyhawk | last post by:
I would like to sort an Arraylist of objects on multiple properties. For instance, I have a Sort Index property and an ID property (both integers). So, the results of my sort would look like this: sort index, id 1000,1 1000,2 1000,3 1001,1 1001,2
1
7194
KevinADC
by: KevinADC | last post by:
Introduction In part one we discussed the default sort function. In part two we will discuss more advanced techniques you can use to sort data. Some of the techniques might introduce unfamiliar methods or syntax to a less experienced perl coder. I will post links to online resources you can read if necessary. Experienced perl coders might find nothing new or useful contained in this article. Short Review In part one I showed you some...
3
7349
KevinADC
by: KevinADC | last post by:
If you are entirely unfamiliar with using Perl to sort data, read the "Sorting Data with Perl - Part One and Two" articles before reading this article. Beginning Perl coders may find this article uses unfamiliar terms and syntax. Intermediate and advanced Perl coders should find this article useful. The object of the article is to inform the reader, it is not about how to code Perl or how to write good Perl code, but to teach the Schwartzian...
5
3188
by: lemlimlee | last post by:
hello, this is the task i need to do: For this task, you are to develop a Java program that allows a user to search or sort an array of numbers using an algorithm that the user chooses. The search algorithms that can be used are Linear Search and Binary Search. The sorting algorithms are bubble, selection and Insertion sort. First, the user is asked whether he/she wants to perform a search option, a sort operation, or exit the program. If...
5
4962
by: jrod11 | last post by:
hi, I found a jquery html table sorting code i have implemented. I am trying to figure out how to edit how many colums there are, but every time i remove code that I think controls how many colums there are, it crashes. There are currently 6 columns, and I only want 4. How do I remove the last two (discount and date)? Here is a link: http://www.jaredmoore.com/tablesorter/docs/salestable.html Here is some jquery js that I think...
0
10613
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. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10363
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 captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10368
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 most users, this new feature is actually very convenient. If you want to control the update process,...
0
9186
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7649
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 instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5544
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 the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
4327
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
2
3846
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
3008
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.