2015-07-19 50 views
4

斷言兩個列表清單的最佳方式是否相等,沒有順序的重要性?例如這兩個列表是相等的:斷言在Python中沒有順序的列表相等列表

a = [[1,2], [3,4]] 
b = [[4,3], [2,1]] 

assert lists_equal_without_order(a, b) # True 

如何lists_equal_without_order來實現,最好使用一些Python現有的斷言?

+1

我以爲你是一個學生尋求作業的幫助,直到我看到你的代表。 ;) –

+0

我假設你仍然希望允許重複(沒有這樣設置外部列表),我們可能不會假設元素的可哈希性或自然排序順序? –

+0

子列表的大小始終是2,大小相等還是大小可變? –

回答

1

如果ab, 中的項目中沒有重複項,則可以使用集合理解來收集每個項目的凍結集。 例如,

In [106]: {(frozenset(item)) for item in a} 
Out[106]: {frozenset({1, 2}), frozenset({3, 4})} 

然後測試,如果這些集合相等:

In [107]: {(frozenset(item)) for item in a} == {(frozenset(item)) for item in b} 
Out[107]: True 

此操作,因爲集沒有秩序,frozensets是哈希的(因此可以是一組的元件)。如果沒有重複,然後frozenset平等,使[1,2][2,1]相當於:

In [109]: frozenset([1,2]) == frozenset([2,1]) 
Out[109]: True 

但要注意的是,如果有重複,那麼frozensets將使[1,1,2]相當於[2,2,1]

In [108]: frozenset([1,1,2]) == frozenset([1,2,2]) 
Out[108]: True 
0

好運行一個循環考慮清單的大小。

A =列表;

B =列表B;

對於i從0運行:環的尺寸

{ 溫度= A [1];

如果(溫度是在存在組B)從乙 刪除臨時;

}

如果B是空集則A = B;

否則 !A = B

+0

感謝您的努力,但我正在專門尋找Python代碼,並且我不確定您的解決方案是否可行。 –

1

如果性能是不是一個因素,一個簡單的解決辦法是先內部列表進行排序,然後外列表進行排序,然後對它們進行比較。

示例 -

def lewo(l1, l2): 
    l1new = [sorted(i) for i in l1] 
    l2new = [sorted(i) for i in l2] 
    l1newsorted = sorted(l1new) 
    l2newsorted = sorted(l2new) 
    return l1newsorted == l2newsorted 

或者更簡潔 -

def lewo(a, b): 
    a_s, b_s = map(sorted, a), map(sorted, b) 
    return sorted(a_s) == sorted(b_s) 
+0

我喜歡這種方法,在這裏我看不到很大的性能損失。 –

2

一個版本,只有一束假設的作品:

def lists_equal_without_order(a, b): 
    """ 
    We don't care about duplicates in list comparison or the sublist comparison. 
    * [1,2,2] === [1,1,2] # True 
    * [[1,1], [1,1]] == [[1,1]] # True 
    The element lists are either the same length or we don't care about duplicates 
    * [1,1,1] === [1] # True 
    """ 
    for l1 in a: 
     check_list = frozenset(l1) 
     if not any(check_list.issuperset(l2) for l2 in b): 
      return False 
    return True 

a = [[1,2], [3,4]] 
b = [[4,3], [2,1]] 

print lists_equal_without_order(a, b) # True 

a = [[1,1], [2,2]] 
b = [[1,2], [2,1]] 

print lists_equal_without_order(a, b) # False 

一個版本弄亂原始列表:

def lists_equal_without_order(a, b): 
    """ 
    This will manipulate the original lists. 
    """ 
    for l1 in a: 
     l1.sort() 
     for l2 in b: 
      l2.sort() 
      if l1 == l2: 
       b.remove(l2) 
       break 
     else: 
      return False 
    return True 

a = [[1,2], [3,4]] 
b = [[4,3], [2,1]] 

print lists_equal_without_order(a, b) # True 

a = [[1,1], [2,2]] 
b = [[1,2], [2,1]] 

print lists_equal_without_order(a, b) # False 

一個版本,做設有專櫃完全匹配,但並不需要保持名單的2份內存:

from collections import Counter 

def lists_equal_without_order(a, b): 
    """ 
    This will make sure the inner list contain the same, 
    but doesn't account for duplicate groups. 
    """ 
    for l1 in a: 
     check_counter = Counter(l1) 
     if not any(Counter(l2) == check_counter for l2 in b): 
      return False 
    return True 

a = [[1,2], [3,4]] 
b = [[4,3], [2,1]] 

print lists_equal_without_order(a, b) # True 

a = [[1,1], [2,2]] 
b = [[1,2], [2,1]] 

print lists_equal_without_order(a, b) # False 
+0

我認爲使用'sorted()'而不是'inplace'.sort()'會更好,我認爲在斷言期間導致實際數據改變並不合適。 –

+0

@AnandSKumar絕對真實,JonClements剛發佈的內容看起來很棒。 –

+0

@AnandSKumar我有點無聊,並增加了兩個解決方案。一個使用frozenset的靈感來自其他答案,但忽略了所有級別的重複項目和一個使用Counter。這些不需要創建列表的完整副本來進行比較。 –

1

如果在子列表沒有重複(或複製可以忽略不計),這種方法的工作原理:

def lists_equal_without_order(a, b): 
    return set_repr(a) == set_repr(b) 

def set_repr(x): 
    return {frozenset(item) for item in x} 

如果我們需要考慮在子列表中重複的,我們需要改用frozensets的計數器:

from collections import Counter 

def lists_equal_without_order(a, b): 
    return counter_repr(a) == counter_repr(b) 

def counter_repr(x): 
    return {frozenset(Counter(item).items()) for item in x} 

如果子列表本身可以出現多次(即,如果外部列表包含重複),我們可以用一個櫃檯外列表:

from collections import Counter 

def lists_equal_without_order(a, b): 
    return counter_repr(a) == counter_repr(b) 

def counter_repr(x): 
    return Counter(frozenset(Counter(item).items()) for item in x) 
0

不同set/frozenset方法:

a = [[1,2], [3,4]] 
b = [[4,3], [2,1]] 

def lists_equal_without_order(lst0, lst1): 
    set0 = set(frozenset(item) for item in lst0) 
    set1 = set(frozenset(item) for item in lst1) 
    return set0 == set1 

print(lists_equal_without_order(a,b)) 

我不能完全肯定它涵蓋了所有的用例。作品爲你給的例子雖然...