The thread on sorting in Python 3 got me to thinking. How could I sort a
list of complex numbers using key?
[(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:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: no ordering relation is defined for complex numbers
This works:
[(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:
[(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:
[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
list of complex numbers using key?
>>lst = [random.random() +random.random( )*1j for i in range(10)]
>>lst
>>lst
As expected:
>>sorted(lst)
File "<stdin>", line 1, in <module>
TypeError: no ordering relation is defined for complex numbers
This works:
>>sorted(lst, key=lambda x: x.real)
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)
(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)
>>pprint.pprint (lst)
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
Comment