2014-09-04 6 views
4

Мне нужен тип данных типа bag/multiset в Python. Я понимаю коллекции. Часто используется для этой цели. Но операторы сравнения, похоже, не работают:Сравнение счетчиков Python как типа Bag

In [1]: from collections import Counter 

In [2]: bag1 = Counter(a=1, b=2, c=3) 

In [3]: bag2 = Counter(a=2, b=2) 

In [4]: bag1 > bag2 
Out[4]: True 

Это кажется ошибкой для меня. Я ожидал, что операторы с меньшим и большим числом, чем операторы, будут выполнять сопоставления подмножеств и суперсети. Но если это так, то bag1 > bag2 будет ложным, потому что bag2 содержит дополнительные 'a'. На объектах Counter также нет методов подмножества/надмножества. Поэтому у меня есть два вопроса:

  1. Какая сравнительная логика используется для объектов Counter?
  2. Как сравнить объекты Counter для подмножества, надмножества, правильного подмножества и собственного суперсета?
+0

Вы читали документацию? – jonrsharpe

+0

Да, если вы имеете в виду здесь: https://docs.python.org/2/library/collections.html#collections.Counter Они описывают это как мешок/мультимножество, я предположил, что это означает, что операторы сравнения будут иметь смысл. –

+0

Я не видел связанный с ним вопрос, и я вижу, как это связано, но у него есть пара вопросов: нет описания того, как реализовать правильное подмножество, хотя я предполагаю, что '<=' и '! =', хотя я не знаю ow, если есть лучший способ реализовать и расшифровать, хотя я думаю, что это инверсия подмножества. Также в принятом ответе есть опечатка, на которую комментарий обращает внимание. Не уверен, что кто-то может это изменить. –

ответ

1

На Python 2, сравнение падает обратно в default sort order for dictionaries (Counter является подклассом dict).

Сопряжения (словари) сравнивают одинаковые, если и только если их отсортировано (key, value) list compare equal. [5] Исходы, отличные от равенства, равны , которые разрешены последовательно, но не определены иначе. [6]

На Python 3, the comparison raises a TypeError:

Отображения (словари) сравнить равны тогда и только тогда, когда они имеют одинаковые пары (ключ, значение). Сравнение заказов ('<', '< =', '> =', '>') raise TypeError.

+0

Я Python 2.7, извините забыл упомянуть. –

+0

Кроме того, сравнение по адресу памяти, похоже, не происходит здесь: id (bag1) - 4371127560, а id (bag2) - 4371127856. Таким образом, 'bag2' должен быть больше, чем' bag1'. –

+0

@WilliamReed: Заказ, который вы видите, является произвольным. –

0

Этот вопрос без ответа представляет интерес:

Как можно сравнивать объекты Счетчик подмножестве, надмножеству, правильное-подмножество и надлежащего-надмножеству?

Определяя недостающие «богатые методы сравнения». Вы можете также использовать свободные функции вместо этого, что сделает код клиента более явным.

from collections import Counter 

class PartiallyOrderedCounter(Counter): 

    def __le__(self, other): 
     """ Multiset inclusion """ 
     return all(v <= other[k] for k,v in self.items()) 


    def __lt__(self, other): 
     """ Multiset strict inclusion """ 
     return self <= other and self != other 


    # TODO : __ge__ and __gt__ 
    # Beware : they CANNOT be written in terms of __le__ or __lt__ 


a = PartiallyOrderedCounter('abc') 
b = PartiallyOrderedCounter('ab') 
c = PartiallyOrderedCounter('abe') 

assert a <= a 
assert not a < a  
assert b <= a 
assert b < a 
assert not a < b  
assert not c <= a 
assert not a <= c