訣竅是讓你的key
函數在第一個索引中返回一個保證可比類型的元組,並在後續索引中返回不同類型的元組。
雖然不是100%相同的都是Python 2呢,爲你的具體情況「號碼前,一切由類型名稱相比,」你可以用一個合理有效key
功能做到這一點:
>>> from numbers import Number
>>> seq = ['Z', 3, 'Y', 1, 'X', 2.5, False, (1, 2), [2, 3], None]
>>> sorted(seq, key=lambda x: (x is not None, '' if isinstance(x, Number) else type(x).__name__, x))
[None, False, 1, 2.5, 3, [2, 3], 'X', 'Y', 'Z', (1, 2)]
這裏的key
函數使得key
的第一個元素簡單地爲bool
,迫使None
在其他所有事情(Py2做同樣的事情)之前排序,然後通過使用空字符串爲鍵的第二部分首先排序所有數字類型,其中一切都使用他們的類型名稱(也像Py2)。一旦你超過了前兩個指數,剩下的就是相同的類型,並且應該比較好。
這裏的主要缺陷是set
和frozenset
等可比較的非數字類型不會相互比較,它們將僅按類型名排序(使用異常的自定義鍵類可以處理此問題)。
它也不會處理遞歸的情況;如果序列包含[2, 3]
和['a', 'b']
,它將有一個TypeError
比較2
和'a'
,但是沒有什麼可以用一個可笑的關鍵類來處理。
如果這不是問題,這是運行便宜,相對簡單。
不同於涉及的自定義類與定義執行比較__lt__
解決方案,該方法具有產生內置鍵,其與所述排序中的Python的高級代碼的最小有效地執行比較的優點。
時序:
# Multiply out the sequence so log n factor in n log n work counts for something
>>> seq = ['Z', 3, 'Y', 1, 'X', 2.5, False, (1, 2), [2, 3], None] * 100
# Verify equivalence
>>> sorted(seq, key=Py2Key) == sorted(seq, key=lambda x: (x is not None, '' if isinstance(x, Number) else type(x).__name__, x))
True
# Timings in seconds for the fastest time (of 3 trials) to run the sort 1000 times:
>>> import timeit
# Py2Key class
>>> min(timeit.repeat('sorted(seq, key=Py2Key)', 'from __main__ import seq, Py2Key', number=1000))
5.251885865057375
>>> min(timeit.repeat('sorted(seq, key=lambda x: (x is not None, "" if isinstance(x, Number) else type(x).__name__, x))', 'from __main__ import seq, Number', number=1000))
1.9556877178131344
基本上,避免動態的Python級__lt__
的開銷是由剛剛超過60%減少的運行時間。它似乎沒有算法上的改進(一個seq
具有相同的運行時間比率的100倍),只是減少了固定開銷,但這是一個不小的縮減。
你期待什麼結果?你期望如何排序字符串和元組? – jprockbelly
你會怎麼樣?''''與'13'排序?您需要提出明確的排序順序。一旦你完成了,你幾乎已經完成了。 –