Skip to content

Instantly share code, notes, and snippets.

@spumer
Created August 23, 2021 07:48
Show Gist options
  • Save spumer/7b7e350db279f5a3cef90a4cfde2f41f to your computer and use it in GitHub Desktop.
Save spumer/7b7e350db279f5a3cef90a4cfde2f41f to your computer and use it in GitHub Desktop.
AnyDict, UnorderedList
import collections
from collections import UserDict
from collections import UserList
def maybe_hdict(value):
if isinstance(value, dict) and not isinstance(value, HDict):
return HDict(value)
return value
class HDict(UserDict):
def __hash__(self):
return hash(frozenset((k, maybe_hdict(v)) for k, v in self.items()))
# inherit from HDict to workaround dict comparision optimization:
# __eq__ not called if .keys() differ, but calls for sub-types
class AnyDict(HDict):
"""
>>> # Если ключа нет, он равен ANY
>>> any_dict = AnyDict({'key': 1})
>>> extra_key_dict = {'key': 1, 'new_key': 2}
>>> any_dict == extra_key_dict
True
>>> # Если ключи совпадают: то они проверяются
>>> diff_value_dict = {'key': 2}
>>> any_dict == diff_value_dict
False
"""
def __eq__(self, other):
if not isinstance(other, collections.Mapping):
return False
for key, value in self.items():
if key not in other:
return False
if other[key] != value:
return False
return True
class UnorderedList(UserList):
"""
>>> l1 = UnorderedList([1, 2, 3])
>>> l2 = UnorderedList([3, 2, 1])
>>> l1 == l2
True
>>> l1 = UnorderedList([{'id': 1}, {'id': 2}])
>>> l2 = UnorderedList([{'id': 2}, {'id': 1}])
>>> l1 == l2
True
"""
def __init__(self, initlist):
copy = [maybe_hdict(item) for item in initlist]
super().__init__(copy)
def __eq__(self, other):
if not isinstance(other, UnorderedList):
other = UnorderedList(other)
return compare(self, other)
def compare(s, t):
"""Compare with O(n * n) complexity
but AnyDict __eq__ logic works correctly
"""
t = list(t)
for elem in s:
if elem in t:
t.remove(elem)
else:
return False
return not t
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment