2013-04-15 45 views
3

所以在Python 2,你可以使用類似什麼是找到獨特的unhashable unorderable類型在Python 3

>>> items = [[1, 2], [3], [3], 4, 'a', 'b', 'a'] 
>>> from itertools import groupby 
>>> [k for k, g in groupby(sorted(items))] 
[4, [1, 2], [3], 'a', 'b'] 

效果很好,在O(N log N)時間的最佳方式。然而Python 3感嘆TypeError: unorderable types: int() < list()。那麼在Python 3中完成它的最好方法是什麼? (我知道最好的是一個主觀的術語,但真的應該有一種方法,根據Python做到這一點)

編輯:它不必使用排序,但我猜這將是最好的方式

+0

那些列表可以不是元組嗎? –

+0

@JakobBowyer原諒我沒有想到一個更好的例子,爲了這個問題,它的標題,讓我們說他們不能 – user2282357

+1

@JakobBowyer:這不會有什麼幫助;那麼他只會得到一個關於'int'和'tuple'不可訂購的錯誤。 – abarnert

回答

5

在2.x中,兩個不可分的內置類型的值按類型排序。沒有定義類型的順序,除了在解釋器的一次運行期間它將保持一致。所以,2 < [2]可能是真或假,但它會是一致是真是假。

在3.x中,無比內置類型的值是無法比擬的,這意味着它們養TypeError如果您嘗試對它們進行比較。所以,2 < [2]是一個錯誤。而且,至少從3.3開始,類型本身甚至沒有可比性。但是如果你想重現的只是2.x行爲,那麼它們在解釋器運行期間是絕對可比的並且是一致的。所以:

sorted(items, key=lambda x: (id(type(x)), x)) 

對於您的用例,這就是您所需要的。


然而,這將不會是準確的是2.x的做同樣的事情,因爲這意味着,例如,1.5 < 2可以是False(因爲float>int)。如果您想要複製確切的行爲,則需要編寫一個首先嚐試比較值的關鍵函數,然後在TypeError上返回比較類型。

這是極少數情況下舊式cmp功能是一個容易得多比一個新型key函數讀取一個,所以讓我們寫這些的一個,然後在其上使用cmp_to_key

def cmp2x(a, b): 
    try: 
     if a==b: return 0 
     elif a<b: return -1 
     elif b<a: return 1 
    except TypeError: 
     pass 
    return cmp2x(id(type(a)), id(type(b))) 
sorted(items, key=functools.cmp_to_key(cmp2x)) 

這仍然不能保證相同的順序不同類型的2.X將給出兩個值之間,但由於2.x中沒有定義任何命令(只是它一個運行中的一致),有沒有辦法它可以。但是,如果你定義一個類的對象不是完全有序的,它們將最終按照相等的順序進行排序,而我不確定這是2.x會做的同樣的事情在這種情況下。

+0

我不是Python專家,但是,是不是應該解決這類問題的字典? '{「key」:value,...}' – user2244984

+1

@ user2244984:我不確定字典如何解決與原始問題相關的任何問題。集合會......但整個問題是值不可散列,這意味着它們不能用於集合或字典。 – abarnert

+0

好的,我需要一個**不可取的定義**,因爲這是我第一次讀這個術語的時間:什麼是不可哈呢? – user2244984

1

讓我們退後一步。

你想uniquify集合。

如果值是哈希的,你應該使用O(N)set解決方案。但他們不是。如果你能想出某種散列函數,你可以等效地使用的myhash(value): value。如果你的使用情況真的是「沒有什麼,但可哈希值和平板list小號可哈希值」,你可以做到這一點try荷蘭國際集團以hash,然後回落到hash(tuple())。但總的來說,這是行不通的。

如果它們是完全有序的,那麼您可以使用O(N log N)sorted解決方案(或等價的基於樹的解決方案或類似方法)。如果您可以想出某種完整的訂購功能,您只需將key傳遞給sorted函數即可。我認爲這將在你的用例中起作用(因此我的其他答案)。但是,如果不是的話,沒有O(N日誌N)解決方案將工作。

如果他們沒有,你可以回落到O(N ** 2)線性搜索解決方案:

unique = [] 
for value in items: 
    if value not in unique: 
     unique.append(value) 

如果你不能找到一些方式來定義一個完整的排序或哈希函數對你的值,這是你能做的最好的。

相關問題