2011-11-30 29 views
6

我有一個字典,其中一些值是不可散列的。我需要一些方法來比較這些無序組,以確保它們包含相同的元素。我不能使用列表,因爲列表相等需要考慮順序,但集合將不起作用,因爲字典不可排列。我瀏覽了python文檔,看起來有用的唯一東西是dict的視圖,在某些情況下它是可散列的,但在這種情況下,這並沒有幫助,因爲其中一個值是包含列表本身的對象,這意味着該詞典的觀點也不會混亂。無序對象的無序集合?

是否有像這樣的情況的標準容器,或者我應該只使用列表並遍歷這兩個列表中的每個元素,並確保一個相等的元素在另一個列表中的某處?

+2

我已經有過類似的情況ons我將dict複製到一個臨時的排序列表中,僅供比較。大小或其他考慮可能會或可能不會使您成爲一個很好的選擇。 –

+0

究竟是什麼讓他們難以爲繼?如果它們不可排除,那你究竟如何比較它們的平等? –

+0

@Karl字典中的一個值是一個列表。 – Macha

回答

11

當不存在重複條目,通常的選擇是:

  1. 如果元素是可哈希:set(a) == set(b)

  2. 如果這些元素均訂購:sorted(a) == sorted(b)

  3. 如果所有你有平等:len(a) == len(b) and all(x in b for x in a)

如果您有重複和它們的多樣性問題,選用的是:

  1. 如果元素是可哈希:Counter(a) == Counter(b)

  2. 如果這些元素均訂購:sorted(a) == sorted(b)

  3. 如果你有等於:len(a) == len(b) and all(a.count(x) == b.count(x) for x in a)

2

我認爲最簡單的方法是使用列表。

group_1 = my_dict_1.values() 
group_2 = my_dict_2.values() 

你比較不會那麼如果爲了要緊,或者如果值是哈希的,但下面應該工作一樣簡單:

def contain_the_same(group_1, group_2): 
    for item in group_1: 
     if item not in group_2: 
      return False 
     else: 
      group_2.pop(group_2.index(item)) 
    if len(group_2) != 0: 
     return False 
    return True 

這應該能夠處理unhashable對象就好了:

>>> contain_the_same([1,2,3], [1,2,3]) 
True 
>>> contain_the_same([1,2,3], [1,2,3,4]) 
False 
>>> contain_the_same([1,2,[3,2,1]], [1,2,[3,2,1]]) 
True 
>>> contain_the_same([5,1,2,[3,2,1,[1]]], [1,[3,2,1,[1]],2,5]) 
True 

一個告誡:如果一個列表中有重複,但沒有其他列表,則返回false。如果你想要做出這種允許的情況,這將需要一些修改。

編輯:甚至更​​容易:

sorted(my_dict_1.values()) == sorted(my_dict_1.values()) 

它甚至看起來這是快兩倍,我contain_the_same功能:

>>> timeit("contain_the_same([5,1,2,[3,2,1,[1]]], [1,[3,2,1,[1]],2,5])", 
      "from __main__ import contain_the_same", number=10000)/10000 
8.868489032757054e-06 
>>>timeit("sorted([5,1,2,[3,2,1,[1]]]) == sorted([1,[3,2,1,[1]],2,5])", 
      number=10000)/10000 
4.928951884845034e-06 

雖然它不會那麼容易延伸到允許重複的情況。