排序复数列表 [英] sorting list of complex numbers

查看:103
本文介绍了排序复数列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Python 3中的排序线程让我思考。我怎么能用键对一个复数的列表进行排序?


>> lst = [random.random()+ random.random()* 1j for i in range(10)]
lst



[(0.32672251849959244 + 0.41428983433288791j),(0.35238056484609881 + 0.92758203977208264j),(0.19337824038125528 + 0.16527285180541951j),(0.47569307114525849 + 0.72381960418815128j),(0.21498813135082351 + 0.2046308266222292j),(0.30142745756937939 + 0.35216751451102601j ),(0.77355676386939132 + 0.0023447924287695043j),(0.2547736124606309 + 0.52234837788936905j),(0.38349189081350132 + 0.62017617694427096j),(0.58362096773561245 + 0.87702443273108477j)]


正如所料:
< blockquote class =post_quotes>


>> sorted(lst)



回溯(最重要的是分最后一次调用):

文件"< stdin>",第1行,< module>
TypeError:没有为复数定义排序关系


这是有效的:


>>已排序(lst,key = lambda x:x.real)



[(0.19337824038125528 + 0.16527285180541951j),(0.21498813135082351 + 0.2046308266222292j ),(0.2547736124606309 + 0.52234837788936905j),(0.30142745756937939 + 0.35216751451102601j),(0.32672251849959244 + 0.41428983433288791j),(0.35238056484609881 + 0.92758203977208264j),(0.38349189081350132 + 0.62017617694427096j),(0.47569307114525849 + 0.72381960418815128j),(0.58362096773561245 + 0.87702443273108477j) ,(0.77355676386939132 + 0.0023447924287695043j)]


但是,如果我想按真实,虚构的部分排序怎么办?这里有更长的

列表,包含20个元素,其中只有10个不同的实数,但是20个不同的

虚构:

< blockquote class =post_quotes>


>> pprint.pprint(lst)



[(1 + 2.73j),

(9 + 3.77j),

(7 + 27j),

(8 + 28j),

(2 + 2.8600000000000003j),

(4 + 3.1200000000000001j),

(2 + 22j),

(9 + 29j),

(3 + 2.9900000000000002j),

(6 + 26j),

2.6000000000000001 j,

(8 + 3.6400000000000001j),

(3 + 23j),

(5 + 3.25j),

(1 + 21j),

(5 + 25j),

20j,

(6 + 3.3799999999999999j),

(7 + 3.5100000000000002j),

(4 + 24j)]


我可以根据实际零件进行排序:


>> lst.sort(key = lambda x:x.real)
pprint.pprint(lst)



[2.6000000000000001j,

20j,

(1 + 2.73j),

(1 + 21j),

(2 + 2.8600000000000003j),

(2 + 22j),

(3 + 2.9900000000000002j),

(3+ 23j),

(4 + 3.1200000000000001j),

(4 + 24j),

(5 + 3.25j),
(5 + 25j),

(6 + 26j),

(6 + 3.3799999999999999j),

(7 + 27j),

(7 + 3.5100000000000002j),

(8 + 28j),

(8 + 3.6400000000000001j),

(9 + 3.77j),

(9 + 29j)]


但我如何进行二次排序呢?想象部分,保留现实部分的现有订单?好像我必须求助于一个

Schwartzian变换并将复数映射到元组,然后将它们排序,然后

将它们映射回来。使用cmp键,

定义所需的compare-real-then-imag函数将是一项相当简单的任务。


有没有办法只使用键arg,没有额外的数据结构吗?


跳过

解决方案

sk ** @ pobox.com 写道:


我可以按实际部分排序罚款:


>> lst.sort(key = lambda x:x.real)

>> pprint.pprint(lst)



[2.6000000000000001j,

20j,

(1 + 2.73j),

(1 + 21j),

(2 + 2.8600000000000003j),

(2+) 22j),

(3 + 2.9900000000000002j),

(3 + 23j),

(4 + 3.1200000000000001j),
(4 + 24j),

(5 + 3.25j),

(5 + 2) 5j),

(6 + 26j),

(6 + 3.3799999999999999j),

(7 + 27j),

(7 + 3.5100000000000002j),

(8 + 28j),

(8 + 3.6400000000000001j),

(9 + 3.77j),

(9 + 29j)]


但我如何通过虚部进行二次排序,保留

实际零件的现有订购?好像我必须求助于一个

Schwartzian变换并将复数映射到元组,然后将它们排序,然后

将它们映射回来。使用cmp键,

定义所需的compare-real-then-imag函数将是一项相当简单的任务。


有没有办法只使用密钥arg,没有额外的数据结构吗?



元组是一个额外的数据结构吗?


>> lst.sort(key = lambda x:(x.real,x.imag))
pprint.pprint(lst)



[2.6000000000000001j,

20j,

(1 + 2.73j),

(1 + 21j),

(2 + 2.8600000000000003j),

(2 + 22j),

(3 + 2.9900000000000002j),

(3 + 23j),

(4 + 3.1200000000000001j),

(4 + 24j),

(5 + 3.25j),

(5 + 25j),

(6 + 3.3799999999999999j),

(6 + 26j) ,

(7 + 3.5100000000000002j),

(7 + 27j),

(8 + 3.6400000000000001j),

(8 + 28j),

(9 + 3.77j),

(9 + 29j)]


如果你不喜欢这个元组,那么就分别进行两种排序:


>> lst.sort(key = lambda x:x.imag)
lst.sort(key = lambda x:x.real)
pprint.pprint(lst )



[2.6000000000000001j,

20j,

(1+) 2.73j),

(1 + 21j),

(2 + 2.8600000000000003j),

(2 + 22j),
(3 + 2.9900000000000002j),

(3 + 23j),

(4 + 3.1200000000000001j),

( 4 + 24j),

(5 + 3.25j),

(5 + 25j),

(6 + 3.3799999999999999j),

(6 + 26j),

(7 + 3.5100000000000002j),

(7 + 27j),

(8 + 3.6400000000000001j),

(8 + 28j),

(9 + 3.77j),

(9 + 29j)]


>>>


sk**@pobox.com schrieb:


Python 3中的排序线程让我思考。如何使用密钥对复杂数字列表进行排序?


>> lst = [random.random()+ random.random()* 1j for i in range(10)]

>> lst



[(0.32672251849959244 + 0.41428983433288791j),(0.35238056484609881 + 0.92758203977208264j),(0.19337824038125528 + 0.16527285180541951j),(0.47569307114525849 + 0.72381960418815128j),(0.21498813135082351 + 0.2046308266222292j),(0.30142745756937939 + 0.35216751451102601j),(0.77355676386939132 + 0.0023447924287695043j),(0.2547736124606309 + 0.52234837788936905j),(0.38349189081350132 + 0.62017617694427096j),(0.58362096773561245 + 0.87702443273108477j)]


正如所料:


>> sorted(lst)



Traceback(最近一次调用最后一次) :

文件"< stdin>&qu ot;,第1行,在< module>中

TypeError:没有为复数定义订购关系


这样有效:


>> sorted(lst,key = lambda x:x.real)



[(0.19337824038125528 + 0.16527285180541951j),(0.21498813135082351 + 0.2046308266222292j),(0.2547736124606309 + 0.52234837788936905j),(0.30142745756937939 + 0.35216751451102601j),(0.32672251849959244 + 0.41428983433288791j),(0.35238056484609881 + 0.92758203977208264j),(0.38349189081350132 + 0.62017617694427096j),(0.47569307114525849 + 0.72381960418815128j),(0.58362096773561245 + 0.87702443273108477j),(0.77355676386939132 + 0.0023447924287695043j)]


但如果我想按真实排序,那么想象一下部分?这里有更长的

列表,包含20个元素,其中只有10个不同的实数,但是20个不同的

虚构:

< blockquote class =post_quotes>
>> pprint.pprint(lst)



[(1 + 2.73j),

(9 + 3.77j),

(7 + 27j),

(8 + 28j),

(2 + 2.8600000000000003j),

(4 + 3.1200000000000001j),

(2 + 22j),

(9 + 29j),

(3 + 2.9900000000000002j),

(6 + 26j),

2.6000000000000001j,

(8 + 3.6400000000000001j),

(3 + 23j),

(5 + 3.25j),

(1 + 21j),

(5 + 25j),

20j,

(6 + 3.3799999999999999j),

(7 + 3.5100000000000002j ),

(4 + 24j)]


我可以按照实际零件进行排序:


>> lst.sort(key = lambda x:x.real)

>> pprint.pprint(lst)



[2.6000000000000001j,

20j,

(1 + 2.73j),

(1 + 21j),

(2 + 2.8600000000000003j),

(2 + 22j),

(3 + 2.9900000000000002j ),

(3 + 23j),

(4 + 3.1200000000000001j),

(4 + 24j),

(5 + 3.25j),

(5 + 25j),

(6 + 26j),

(6 + 3.3799999999999999 j),

(7 + 27j),

(7 + 3.5100000000000002j),

(8 + 28j),

(8 + 3.6400000000000001j),

(9 + 3.77j),

(9 + 29j)]


但是我如何通过虚部进行二次排序,保留实际零件上现有的

排序?好像我必须求助于一个

Schwartzian变换并将复数映射到元组,然后将它们排序,然后

将它们映射回来。使用cmp键,

定义所需的compare-real-then-imag函数将是一项相当简单的任务。


有没有办法只使用密钥arg,没有额外的数据结构吗?



没有(未经测试)


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


工作吗?


Diez


< blockquote class =post_quotes>
> Timeit建议返回真实的单一排序,图像元素比一个字段上的两个排序更快,正如您可能期望的那样,因为更少的调用关键功能。



Steve当然是数字的一半。关键的优势

史蒂夫函数是每个元素只需要一次调用

StevePython函数,然后使用
$ b进行比较$ b SteveC编码的比较功能。


SteveBut你已经知道了,对吧?


我知道C比较功能,不是关于关键呼叫的数量。

我假设关键功能在必要时被调用,因为它可能会产生副作用。我确认关键功能是每个元素调用一次

而不是每次比较一次。


谢谢,


跳过


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.32672251849959244+0.41428983433288791j), (0.35238056484609881+0.92758203977208264j), (0.19337824038125528+0.16527285180541951j), (0.47569307114525849+0.72381960418815128j), (0.21498813135082351+0.2046308266222292j), (0.30142745756937939+0.35216751451102601j), (0.77355676386939132+0.0023447924287695043j), (0.2547736124606309+0.52234837788936905j), (0.38349189081350132+0.62017617694427096j), (0.58362096773561245+0.87702443273108477j)]

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.19337824038125528+0.16527285180541951j), (0.21498813135082351+0.2046308266222292j), (0.2547736124606309+0.52234837788936905j), (0.30142745756937939+0.35216751451102601j), (0.32672251849959244+0.41428983433288791j), (0.35238056484609881+0.92758203977208264j), (0.38349189081350132+0.62017617694427096j), (0.47569307114525849+0.72381960418815128j), (0.58362096773561245+0.87702443273108477j), (0.77355676386939132+0.0023447924287695043j)]

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.8600000000000003j),
(4+3.1200000000000001j),
(2+22j),
(9+29j),
(3+2.9900000000000002j),
(6+26j),
2.6000000000000001j,
(8+3.6400000000000001j),
(3+23j),
(5+3.25j),
(1+21j),
(5+25j),
20j,
(6+3.3799999999999999j),
(7+3.5100000000000002j),
(4+24j)]

I can sort by the real parts just fine:

>>lst.sort(key=lambda x: x.real)
pprint.pprint(lst)

[2.6000000000000001j,
20j,
(1+2.73j),
(1+21j),
(2+2.8600000000000003j),
(2+22j),
(3+2.9900000000000002j),
(3+23j),
(4+3.1200000000000001j),
(4+24j),
(5+3.25j),
(5+25j),
(6+26j),
(6+3.3799999999999999j),
(7+27j),
(7+3.5100000000000002j),
(8+28j),
(8+3.6400000000000001j),
(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

解决方案

sk**@pobox.com wrote:

I can sort by the real parts just fine:

>>lst.sort(key=lambda x: x.real)
>>pprint.pprint(lst)

[2.6000000000000001j,
20j,
(1+2.73j),
(1+21j),
(2+2.8600000000000003j),
(2+22j),
(3+2.9900000000000002j),
(3+23j),
(4+3.1200000000000001j),
(4+24j),
(5+3.25j),
(5+25j),
(6+26j),
(6+3.3799999999999999j),
(7+27j),
(7+3.5100000000000002j),
(8+28j),
(8+3.6400000000000001j),
(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.6000000000000001j,
20j,
(1+2.73j),
(1+21j),
(2+2.8600000000000003j),
(2+22j),
(3+2.9900000000000002j),
(3+23j),
(4+3.1200000000000001j),
(4+24j),
(5+3.25j),
(5+25j),
(6+3.3799999999999999j),
(6+26j),
(7+3.5100000000000002j),
(7+27j),
(8+3.6400000000000001j),
(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.6000000000000001j,
20j,
(1+2.73j),
(1+21j),
(2+2.8600000000000003j),
(2+22j),
(3+2.9900000000000002j),
(3+23j),
(4+3.1200000000000001j),
(4+24j),
(5+3.25j),
(5+25j),
(6+3.3799999999999999j),
(6+26j),
(7+3.5100000000000002j),
(7+27j),
(8+3.6400000000000001j),
(8+28j),
(9+3.77j),
(9+29j)]

>>>


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.32672251849959244+0.41428983433288791j), (0.35238056484609881+0.92758203977208264j), (0.19337824038125528+0.16527285180541951j), (0.47569307114525849+0.72381960418815128j), (0.21498813135082351+0.2046308266222292j), (0.30142745756937939+0.35216751451102601j), (0.77355676386939132+0.0023447924287695043j), (0.2547736124606309+0.52234837788936905j), (0.38349189081350132+0.62017617694427096j), (0.58362096773561245+0.87702443273108477j)]

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.19337824038125528+0.16527285180541951j), (0.21498813135082351+0.2046308266222292j), (0.2547736124606309+0.52234837788936905j), (0.30142745756937939+0.35216751451102601j), (0.32672251849959244+0.41428983433288791j), (0.35238056484609881+0.92758203977208264j), (0.38349189081350132+0.62017617694427096j), (0.47569307114525849+0.72381960418815128j), (0.58362096773561245+0.87702443273108477j), (0.77355676386939132+0.0023447924287695043j)]

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.8600000000000003j),
(4+3.1200000000000001j),
(2+22j),
(9+29j),
(3+2.9900000000000002j),
(6+26j),
2.6000000000000001j,
(8+3.6400000000000001j),
(3+23j),
(5+3.25j),
(1+21j),
(5+25j),
20j,
(6+3.3799999999999999j),
(7+3.5100000000000002j),
(4+24j)]

I can sort by the real parts just fine:

>>lst.sort(key=lambda x: x.real)
>>pprint.pprint(lst)

[2.6000000000000001j,
20j,
(1+2.73j),
(1+21j),
(2+2.8600000000000003j),
(2+22j),
(3+2.9900000000000002j),
(3+23j),
(4+3.1200000000000001j),
(4+24j),
(5+3.25j),
(5+25j),
(6+26j),
(6+3.3799999999999999j),
(7+27j),
(7+3.5100000000000002j),
(8+28j),
(8+3.6400000000000001j),
(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


>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


这篇关于排序复数列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆