Skip to content

Commit de56336

Browse files
authored
Merge pull request #403 from bmorck/ignore-list-order
Add Ignore Iterable Order Option to DeepHash
2 parents 38937b1 + b2fcd65 commit de56336

File tree

3 files changed

+22
-1
lines changed

3 files changed

+22
-1
lines changed

deepdiff/deephash.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ def __init__(self,
144144
parent="root",
145145
encodings=None,
146146
ignore_encoding_errors=False,
147+
ignore_iterable_order=True,
147148
**kwargs):
148149
if kwargs:
149150
raise ValueError(
@@ -190,6 +191,7 @@ def __init__(self,
190191
self.ignore_private_variables = ignore_private_variables
191192
self.encodings = encodings
192193
self.ignore_encoding_errors = ignore_encoding_errors
194+
self.ignore_iterable_order = ignore_iterable_order
193195

194196
self._hash(obj, parent=parent, parents_ids=frozenset({get_id(obj)}))
195197

@@ -424,7 +426,9 @@ def _prep_iterable(self, obj, parent, parents_ids=EMPTY_FROZENSET):
424426
'{}|{}'.format(i, v) for i, v in result.items()
425427
]
426428

427-
result = sorted(map(str, result)) # making sure the result items are string and sorted so join command works.
429+
result = map(str, result) # making sure the result items are string so join command works.
430+
if self.ignore_iterable_order:
431+
result = sorted(result)
428432
result = ','.join(result)
429433
result = KEY_TO_VAL_STR.format(type(obj).__name__, result)
430434

docs/deephash_doc.rst

+2
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ ignore_private_variables: Boolean, default = True
123123
ignore_encoding_errors: Boolean, default = False
124124
If you want to get away with UnicodeDecodeError without passing explicit character encodings, set this option to True. If you want to make sure the encoding is done properly, keep this as False and instead pass an explicit list of character encodings to be considered via the encodings parameter.
125125

126+
ignore_iterable_order: Boolean, default = True
127+
If order of items in an iterable should not cause the hash of the iterable to be different.
126128

127129
number_format_notation : string, default="f"
128130
number_format_notation is what defines the meaning of significant digits. The default value of "f" means the digits AFTER the decimal point. "f" stands for fixed point. The other option is "e" which stands for exponent notation or scientific notation.

tests/test_hash.py

+15
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,21 @@ def test_same_sets_same_hash(self):
368368
t2_hash = DeepHashPrep(t2)
369369

370370
assert t1_hash[get_id(t1)] == t2_hash[get_id(t2)]
371+
372+
@pytest.mark.parametrize("list1, list2, ignore_iterable_order, is_equal", [
373+
([1, 2], [2, 1], False, False),
374+
([1, 2], [2, 1], True, True),
375+
([1, 2, 3], [1, 3, 2], False, False),
376+
([1, [1, 2, 3]], [1, [3, 2, 1]], False, False),
377+
([1, [1, 2, 3]], [1, [3, 2, 1]], True, True),
378+
((1, 2), (2, 1), False, False),
379+
((1, 2), (2, 1), True, True),
380+
])
381+
def test_ignore_iterable_order(self, list1, list2, ignore_iterable_order, is_equal):
382+
list1_hash = DeepHash(list1, ignore_iterable_order=ignore_iterable_order)
383+
list2_hash = DeepHash(list2, ignore_iterable_order=ignore_iterable_order)
384+
385+
assert is_equal == (list1_hash[list1] == list2_hash[list2])
371386

372387
@pytest.mark.parametrize("t1, t2, significant_digits, number_format_notation, result", [
373388
({0.012, 0.98}, {0.013, 0.99}, 1, "f", 'set:float:0.0,float:1.0'),

0 commit comments

Comments
 (0)