2011-11-30 28 views
6

Tôi có một dict trong đó một số giá trị không thể băm. Tôi cần một số cách để so sánh hai nhóm không theo thứ tự này để đảm bảo chúng chứa các phần tử bằng nhau. Tôi không thể sử dụng danh sách bởi vì danh sách bình đẳng đưa thứ tự vào tài khoản nhưng bộ sẽ không hoạt động vì dicts không hashable. Tôi đã xem qua tài liệu python và điều duy nhất hữu ích là chế độ xem của dict, có thể băm trong một số trường hợp nhưng trong trường hợp này, điều này không giúp ích hoặc là một trong các giá trị là đối tượng chứa danh sách, có nghĩa là chế độ xem của dict sẽ không thể băm.Bộ sưu tập không có thứ tự cho các đối tượng không thể sửa được?

Có thùng chứa chuẩn cho các tình huống như thế này hay tôi chỉ nên sử dụng danh sách và lặp qua mọi phần tử trong cả hai danh sách và đảm bảo yếu tố bằng nhau ở đâu đó trong danh sách khác?

+2

Tôi đã có vị trí tương tự Tôi đã sao chép dict vào danh sách được sắp xếp tạm thời chỉ để so sánh. Kích thước hoặc cân nhắc khác có thể hoặc không thể làm cho điều này trở thành một lựa chọn tốt cho trường hợp của bạn. –

+0

Chính xác điều gì khiến chúng không thể hoạt động được? Nếu chúng không thể bẻ khóa, bạn chính xác so sánh chúng như thế nào cho sự bình đẳng? –

+0

@Karl Một trong các giá trị trong dict là một danh sách. – Macha

Trả lời

11

Khi mục trùng lặp không tồn tại, sự lựa chọn thông thường là:

  1. Nếu yếu tố này là hashable: set(a) == set(b)

  2. Nếu yếu tố này là orderable: sorted(a) == sorted(b)

  3. Nếu tất cả bạn có sự bình đẳng: len(a) == len(b) and all(x in b for x in a)

Nếu bạn có bản sao và các vấn đề đa dạng của mình, các lựa chọn là:

  1. Nếu yếu tố này là hashable: Counter(a) == Counter(b)

  2. Nếu yếu tố này là orderable: sorted(a) == sorted(b)

  3. Nếu tất cả các bạn có là bình đẳng: len(a) == len(b) and all(a.count(x) == b.count(x) for x in a)

2

Tôi nghĩ phương pháp đơn giản nhất là sử dụng danh sách.

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

so sánh của bạn sẽ không thể đơn giản như nếu thứ tự quan trọng, hoặc nếu các giá trị đã hashable, nhưng sau nên làm việc:

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 

này nên có thể xử lý đối tượng unhashable tốt :

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

Lưu ý: Điều này sẽ trả về false nếu có trùng lặp trong một danh sách, nhưng không có khác. Điều này sẽ yêu cầu một số sửa đổi nếu bạn muốn làm cho rằng một trường hợp cho phép.

Edit: Thậm chí dễ dàng hơn:

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

Nó thậm chí trông như thế này là nhanh gấp hai lần như contain_the_same chức năng của tôi:

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

Mặc dù nó sẽ không được dễ dàng để mở rộng đến trường hợp cho phép trùng lặp.

Các vấn đề liên quan