This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Add method to compare dicts accounting for order
Type: enhancement Stage: resolved
Components: Versions: Python 3.11
process
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: Nosy List: mcarans, rhettinger, serhiy.storchaka, steven.daprano, terry.reedy
Priority: normal Keywords:

Created on 2021-09-03 04:13 by mcarans, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (9)
msg400975 - (view) Author: Michael Rans (mcarans) Date: 2021-09-03 04:13
I suggest adding a method that allows comparing dicts taking into account the order - an ordered compare (since == does not do that).

(Also for my other issue (https://bugs.python.org/issue45092) where I suggested that set be ordered to reduce confusion, the set could also have an ordered compare).
msg400977 - (view) Author: Steven D'Aprano (steven.daprano) * (Python committer) Date: 2021-09-03 04:44
What is your use-case for having dicts that differ only in order compare unequal?

I can't think of any reason why I would want such a comparison, but if I did, it's a trivial one-liner:

    d1 == d2 and all(k1 == k2 for k1, k2 in zip(d1, d2))
msg400978 - (view) Author: Michael Rans (mcarans) Date: 2021-09-03 05:05
My use case is in testing. Currently I use an OrderedDict, but since dict introduced ordering in 3.7, I was considering switching. For my test, I need to check that the dictionary is the same both in content and order. I can indeed use your one liner, but just thought it would be useful to have a method available.
msg400980 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2021-09-03 06:28
For tests it can be more convenient to use

    list(d1.items()) == list(d2.items())

because it can produce better report on failure.

You can add a simple helper function if you use it multiple times in tests.
msg401014 - (view) Author: Michael Rans (mcarans) Date: 2021-09-03 18:57
Thank you. Another case is in round trip processing of JSON or YML. Other cases are where you would prefer an OrderedDict over a dict. 

I think the method would help clarify things because it would make it obvious that it is for ordered comparisons while the existing == does not do that.

eg. something like:
d1.compare_ordered(d2)
or:
d1.compare(d2, ordered=True)  # ordered could be by default True
msg401030 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2021-09-04 02:27
-1 The dict API is too important to be burdened with a mostly useless and rarely needed method.  Besides we already have simple ways to do it, for example:

    assert list(d.items()) == list(e.items())

or:

    assert OrderedDict(d) == OrderedDict(e)
msg401031 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2021-09-04 02:35
-1 also for the reasons given.

Michael, a question asking how would have made a good python-list post. So I posted the answers in "How to include insertion order in dict equality"
msg401035 - (view) Author: Steven D'Aprano (steven.daprano) * (Python committer) Date: 2021-09-04 05:24
> Another case is in round trip processing of JSON or YML.

Sorry for my ignorance, but I don't see how or why an unordered 
comparison would help you with round-tripping JSON or YAML.

The order of key:value pairs in JSON is not guaranteed to be preserved, 
so if you round-trip a dict to JSON back to a dict, and then use an 
ordered comparison, you might wrongly think that they are unequal.

(I think that Python's JSON does preserve order, by default. But other 
JSON encoders might not.)

> Other cases are where you would prefer an OrderedDict over a dict. 

Then use an OrderedDict.
msg401036 - (view) Author: Michael Rans (mcarans) Date: 2021-09-04 05:31
Thanks for all your help and advice.
History
Date User Action Args
2022-04-11 14:59:49adminsetgithub: 89256
2021-09-04 05:31:22mcaranssetmessages: + msg401036
2021-09-04 05:24:13steven.dapranosetmessages: + msg401035
2021-09-04 02:35:34terry.reedysetstatus: open -> closed

nosy: + terry.reedy
messages: + msg401031

resolution: rejected
stage: resolved
2021-09-04 02:27:55rhettingersetmessages: - msg401022
2021-09-04 02:27:46rhettingersetmessages: + msg401030
2021-09-04 00:34:38rhettingersetnosy: + rhettinger
messages: + msg401022
2021-09-03 18:57:00mcaranssetmessages: + msg401014
2021-09-03 06:28:13serhiy.storchakasetnosy: + serhiy.storchaka
messages: + msg400980
2021-09-03 05:05:48mcaranssetmessages: + msg400978
2021-09-03 04:44:56steven.dapranosettype: behavior -> enhancement

messages: + msg400977
nosy: + steven.daprano
2021-09-03 04:14:01mcaranssettype: behavior
2021-09-03 04:13:12mcaranscreate