2011-11-30 14 views
6

Mam dyktando, w którym niektóre wartości nie są nieaktualne. Potrzebuję sposobu na porównanie dwóch nieuporządkowanych grup, aby upewnić się, że zawierają równe elementy. Nie mogę używać list, ponieważ lista równości bierze pod uwagę porządek, ale zestawy nie będą działać, ponieważ dykta nie jest nieaktualna. Przejrzałem dokumentację Pythona, a jedyną rzeczą, która wygląda na użyteczną, jest widok dyktafonu, który w niektórych okolicznościach jest nieczytelny, ale w tym przypadku to nie pomaga, ponieważ jedną z wartości jest obiekt zawierający same listy, co oznacza, że ​​pogląd dyktatora również nie będzie możliwy.Nieuporządkowana kolekcja dla nieusuwalnych obiektów?

Czy istnieje standardowy pojemnik na takie sytuacje, czy powinienem użyć list i przejść przez każdy element na obu listach i upewnić się, że taki sam element znajduje się na innej liście?

+2

Miałem podobne sytuacje gdzie skopiowałem dyktat na tymczasową posortowaną listę tylko dla porównania. Rozmiar lub inne względy mogą, ale nie muszą, być dobrym rozwiązaniem dla twojej sprawy. –

+0

Co dokładnie sprawia, że ​​są nieuszkodzone? Jeśli nie są zgodne ze standardami, jak dokładnie porównujesz je do równości? –

+0

@Karl Jedną z wartości w dyktowaniu jest lista. – Macha

Odpowiedz

11

Kiedy zduplikowane wpisy nie istnieją, zwykłe wybory są:

  1. Jeśli elementy są hashable: set(a) == set(b)

  2. Jeśli elementy są można zamówić: sorted(a) == sorted(b)

  3. Jeśli wszystko masz równość: len(a) == len(b) and all(x in b for x in a)

Jeśli masz duplikatów i ich spraw wielości, do wyboru są:

  1. Jeśli elementy są hashable: Counter(a) == Counter(b)

  2. Jeśli elementy są można zamówić: sorted(a) == sorted(b)

  3. Jeśli wszystko masz jest równość: len(a) == len(b) and all(a.count(x) == b.count(x) for x in a)

2

Myślę, że najprostszą metodą jest użycie list.

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

Twoje porównanie nie będzie tak proste, jakby kolejność znaczenia, czy wartości te hashable, ale następujący powinno działać:

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 

ten powinien być w stanie obsłużyć unhashable obiektów dobrze :

>>> 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 

Ograniczenie: Zwróci wartość false, jeśli na jednej liście znajdują się duplikaty, ale nie inne. To wymagałoby pewnych modyfikacji, gdybyś chciał, aby to było dozwolone.

Edit: Jeszcze prościej

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

nawet wygląda to dwa razy szybciej niż mój contain_the_same funkcję:

>>> 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 

Mimo, że nie będzie tak łatwo rozszerzyć do przypadku, w którym dozwolone są duplikaty.