(â» qiitaã«æ¸ããè¨äºã®ãåãåãã¼ã¸ã§ã³ã§ã)
【Python】並び順を無視してリストを比較するテスト(DeepDiff) - Qiita
- çµè«: deepdiffã使ã
- åæ¸ã
- åèãªã³ã¯
- ç°å¢
- æååã®ãªã¹ã: sortãã¤ãã.
- è¾æ¸ã®ãªã¹ã: keyãæå®ãã¦ã½ã¼ããã.
- è¾æ¸ã®ãªã¹ã: assertCountEqualã使ã.
- valueã«ãªã¹ãããã¤è¾æ¸ã®ãªã¹ã: DeepDiffã使ã
- çµè«
- ã¾ã¨ã
çµè«: deepdiffã使ã
å®ç¾ãããæ¡ä»¶ã¯ä»¥ä¸ã®äºã¤.
- è¾æ¸ãè¦ç´ ã¨ãã¦æã¤ãªã¹ããããããåããªã¹ããããæ¯ã¹ãã.
- ãã ã並ã³é ã¯ç°ãªã£ã¦ãã¦ãè¯ããã¨ã¨ããã
- è¾æ¸ã®ããvalue(ä¸ä¾ã§ã¯
spells
)ããªã¹ãã¨ãªã£ã¦ããã- ãã¡ãã®è¦ç´ ã並ã³é ã¯ç°ãªã£ã¦ãã¦ãè¯ããã¨ã¨ããã
>>> dict_in_list1 [ {'name': 'Reimu', 'spells': ['Musouhuin', 'niju-kekkai']}, {'name': 'Marisa', 'spells': ['non-directional laser', 'star-dust reverie']}, {'name': 'Alice', 'spells': ['hourai-doll', 'shanghai-doll']} ] >>> dict_in_list2 [ {'name': 'Marisa', 'spells': ['star-dust reverie', 'non-directional laser']}, {'name': 'Reimu', 'spells': ['Musouhuin', 'niju-kekkai']}, {'name': 'Alice', 'spells': ['hourai-doll', 'shanghai-doll']} ]
DeepDiffã使ãã¨ã以ä¸ã®ããã«ãã¦åããã¼ã¿ã§ããããæ¯è¼ã§ãã.
pytest
assert not DeepDiff(dict_in_list1, dict_in_list2, ignore_order=True)
unittest
self.assertEqual(DeepDiff(dict_in_list1, dict_in_list2, ignore_order=True), {})
åæ¸ã
ãã¹ãã³ã¼ããæ¸ãã¦ããã¨ãasserté¨åã巨大ã«ãªã£ã¦ãã¾ããè¦éããç®çã®ææ¡ãé£ãããªã£ã¦ãããã¨ãããã¾ãã
ãã¡ããããªãã¹ããã¹ããå°ããåä½ã§æ¸ããã¯ãªãã£ã«ã«ãªé¨åã®ã¿ãã§ãã¯ãããªã©ã®å·¥å¤«ããããã¨ã第ä¸ã§ã¯ããã¾ãã
ããããAPIã®è¿ãå¤ããããå¦çã®çµæãªã©ãããã®ã¾ã¾ç¢ºãããã..ã¨ãã以ä¸ã®ãããªã±ã¼ã¹ãããã¨æãã¾ã.
- ããç¨åº¦ã®ãã¼ã¿ã®çµã¿ãæãã¨æå³ã®éããã¼ã¿ã«ãªããã®.
- ãã¹ããæ¸ããªããéçº/ãªãã¡ã¯ã¿ãã¦ãããç¾å¨ã®è¿ãå¤ãå£ãã¦ããªããã¨ãããªãã¡ã¯ã¿ä¸ã«ç¢ºããããã¹ãããµãã¨ç¨æããã.
ãã®ãããªã±ã¼ã¹ã§ã¯ããªãã¸ã§ã¯ãããã®ã¾ã¾æ¯è¼ããããªãã¾ããããªã¹ãã®è¦ç´ ã並ã³é ãç¡è¦ãã¦æ¯è¼ããã¨ãã¯ãè¦ç´ ã®åã«ãã£ã¦ã¨ã¦ãé£ãããªã£ã¦ãã¾ãã¾ãã
ä»åã¯ãDeepDiffã®ä»ãsortããæ¹æ³ãassertCoutEqualã¡ã½ãããç¨ããæ¹æ³ãç´¹ä»ãããã¨æãã¾ã.
åèãªã³ã¯
GitHub - seperman/deepdiff: Deep Difference and search of any Python object/data.
unittest --- ã¦ããããã¹ããã¬ã¼ã ã¯ã¼ã¯ â Python 3.10.0b2 ããã¥ã¡ã³ã
ç°å¢
ãã¼ã¸ã§ã³ | |
---|---|
MacOS Big Sur | 11.6 |
Python3 | 3.9.1 |
deepdiff | 5.7.0 |
æååã®ãªã¹ã: sortãã¤ãã.
ååã®æ¹ã¯sortããã使ãã¨ãèããã¾ããã
è¦ãç®ã«ãä½ããã£ã¦ãããåããããããã·ã³ãã«ã«ããããããå¯è½ãªéããã¡ãã使ãã¹ãã ã¨æãã¾ã .
æååãªã©ãã½ã¼ãã§ãã(ã¤ã¾ã<
æ¼ç®åã§å¤§å°ãæ¯ã¹ããã¨ãã§ããã__lt__
ãå®ç¾©ããã¦ãã)å ´åã¯ç°¡åã§ã.
以ä¸ã®ãµãã¤ã®ãªã¹ããæ¯è¼ãã¾ãã
å«ã¾ãã¦ããè¦ç´ ã¯åãã§ãããé çªãç°ãªã£ã¦ãããã¨ã«æ³¨æãã¾ãã(åãçµæã ã¨å¤å®ããã.)
names1 = ["Reimu", "Alice", "Marisa"] names2 = ["Reimu", "Marisa", "Alice"]
ãªã¹ãã®æ¯è¼ã¯è¦ç´ ãé ããé çªã«æ¯è¼ããã®ã§ããã®ã¾ã¾ã§ã¯ãã¡ã§ã.
>>> names1 == names2
False
ã½ã¼ããã¾ãã
>>> sorted(names1) == sorted(names2) True
è¾æ¸ã®ãªã¹ã: keyãæå®ãã¦ã½ã¼ããã.
ä»åº¦ã®ä¾ã¯è¾æ¸(dict)ããªã¹ãã®è¦ç´ ã¨ãã¦ä¸¦ãã§ãã¾ãã
å ã»ã©ã¨ä¼¼ã¦ãã¾ãããä»åã¯ãã®ã¾ã¾ã§ã¯ã½ã¼ãã§ãã¾ããã
ä»åã®ä¾ããå«ã¾ãã¦ããè¦ç´ ã¯åãã§ãããé çªãç°ãªã£ã¦ãããã¨ã«æ³¨æãã¾ãã(åãçµæã ã¨å¤å®ããã.)
names1 = [ {"name": "Reimu"}, {"name": "Marisa"}, {"name": "Alice"}, ] names2 = [ {"name": "Alice"}, {"name": "Reimu"}, {"name": "Marisa"}, ]
ã¾ãããã®ã¾ã¾æ¯è¼ããã¨ãã¯Falseã¨ãªãã¾ãã(並ã³é ã¯ç°ãªã£ã¦ãã¦ãããã®ã§, å®éã¯Trueã ã¨å¤å®ããã)
>>> names1 == names2
False
dictå士ã¯<
ã®æåãå®ç¾©ããã¦ããªãã®ã§sortã§ãã¾ããã
>>> sorted(names1) TypeError: '<' not supported between instances of 'dict' and 'dict'
ãã®å ´åãããããã®dictãå¿ ãnameå±æ§ããã¡ãéè¤ããªããªãã°ãkeyãæå®ãããã¨ã§ã½ã¼ããããã¨ãå¯è½ã§ã.
keyãæå®ããã¨ãkey: nameã®valueã®å¤ã§æ¯è¼ãã¦ã½ã¼ããããã¨ã«ãªãã¾ãã
>>> sorted(names1, key=lambda x: x["name"]) [ {'name': 'Alice'}, {'name': 'Marisa'}, {'name': 'Reimu'} ]
keyã«æ¸¡ããé¢æ°lambdaã®ãå¼æ°xã«ådictãé çªã«æ¸¡ããã¾ããããã¦ãdictã®nameãã¼ã«ãããvalueãåãåºããã¦æ¯è¼ã«ä½¿ãããã¤ã¡ã¼ã¸ã§ãã
çµæãé çªã«é¢ä¿ãªãåãè¦ç´ ãå«ãã§ãããã¨ã確ããããã¾ãã.
>>> sorted(names1, key=lambda x: x["name"]) == sorted(names2, key=lambda x: x["name"]) True
keyã§åå¾ããå¤ã¯ã¿ãã«ã«ãªã£ã¦ãè¯ãã®ã§ãnameãã¼ã ãã§ã¯ã½ã¼ãã§ããªãå ´åã対å¿ã§ããã¨æãã¾ã(æªæ¤è¨¼)ã
ãããããã¹ãã³ã¼ãã§ã®ä½¿ç¨ãæ³å®ãã¦ããå ´åãçµæã®æ¯è¼ã®ããã«è¤éãªã½ã¼ãæ¡ä»¶ãæ¸ããã¨ã¯æ éã«èããæ¹ãè¯ãã¨æãã¾ãã
è¾æ¸ã®ãªã¹ã: assertCountEqualã使ã.
ãã®ãããªã±ã¼ã¹ã§ãPythonæ¨æºã®ãã¼ã«ã«ã¯ããä¸ã¤å¼·åãªãã®ãããã¾ãã
unittestã¢ã¸ã¥ã¼ã«ã§ãTestCaseã¯ã©ã¹ã«å®è£ ããã¦ããassertãã«ãã¼ã¡ã½ããã®ã²ã¨ã¤ãassertCountEqualã§ãã
ååã®å°è±¡ã¨ã¯ããªãç°ãªãã¾ããããé çªã«ãããåãè¦ç´ ãåãæ°ã ãããããã¨ãæ¤è¨¼ã§ããassertã¡ã½ããã¨ãªã£ã¦ãã¾ãã
unittest --- ã¦ããããã¹ããã¬ã¼ã ã¯ã¼ã¯ â Python 3.10.0b2 ããã¥ã¡ã³ã
unittestã使ã£ã¦ããå ´åã«ã¯ãself.assertCountEqual
ãå¼ã³åºãã°è¯ãã ãã§ãã®ã§ãä»åã¯pytestãªã©ããã使ç¨ã§ãããããTestCaseãã¤ã³ã¹ã¿ã³ã¹åãã¦ä½¿ãæé ã示ãã¾ã.
æ¯è¼ããã®ã¯ãå ã»ã©keyæå®ãã¦ã½ã¼ããã¦ããdict in listã§ãã
names1 = [ {"name": "Reimu"}, {"name": "Marisa"}, {"name": "Alice"}, ] names2 = [ {"name": "Alice"}, {"name": "Reimu"}, {"name": "Marisa"}, ]
>>> from unittest import TestCase >>> case = TestCase() >>> case.assertCountEqual(names1, names2) # OK!!
ã¨ã¦ã楽ã§ããï¼
å ¬å¼ããã¥ã¡ã³ãã«ä»çµã¿ã«ã¤ãã¦èª¬æãããã¾ãããã»ã¨ãã©ã®çµã¿è¾¼ã¿åã¯ä½ãæèããã«æ¯è¼ã§ãã¾ããèªåã®å ´åãã大æµã®å ´åã¯sortã¨assertCountEqualã®ã©ã¡ããã§äºè¶³ãã¦ãã¾ãã
assertEqual() ã¡ã½ããã¯ãåãåã®ãªãã¸ã§ã¯ãã®ç価æ§ç¢ºèªã®ããã«ãåãã¨ã«ç¹æã®ã¡ã½ããã«ãã£ã¹ããããã¾ãããããã®ã¡ã½ããã¯ãã»ã¨ãã©ã®çµã¿è¾¼ã¿åç¨ã®ã¡ã½ããã¯æ¢ã«å®è£ ããã¦ãã¾ããããã«ã addTypeEqualityFunc() ã使ãäºã§æ°ããªã¡ã½ãããç»é²ãããã¨ãã§ãã¾ã.
é£ç¹ã¯ä»åã®ç®çã§ã¯ãã¡ã½ããå称ãä¸èªç¶ã«ãªã ç¹ãã¨æãã¾ãã
ãã®ååã¯ãä»çµã¿èªä½ãã¨ã¦ããã表ãã¦ãã¾ããåºç¾ãããªãã¸ã§ã¯ããã(collectionã¢ã¸ã¥ã¼ã«ã®)Counterã使ã£ã¦æ°ãä¸ãã¦ããããã§ãã
ãªã®ã§ãé çªãæ°ã«ãããªã¹ããæ¯è¼ãããï¼ãã¨ããã®ã¯ãå¯è½ã§ã¯ããã®ã§ããæ¬æ¥ã®ä½¿ãæ¹ã¨ã¯ã¡ãã£ã¨ããã¦ããã®ããªãã¨æãã¾ãã
å¤åã§ãããassertCountEqualã®æ¬æ¥ã®ä½¿ãæ¹ã¯ãä¸ã®ãããªã±ã¼ã¹ã ã¨æãã¾ãã
>>> fruits1 = ["ããã", "ã¿ãã", "ã¿ãã", "ããã", "ããã"] >>> fruits2 = ["ããã", "ã¿ãã", "ã¿ãã", "ããã", "ã¿ãã"] >>> case.assertCountEqual(fruits1, fruits2) AssertionError: Element counts were not equal: First has 3, Second has 2: 'ããã' First has 2, Second has 3: 'ã¿ãã'
ãã¼ããã¨ã©ã¼ã¡ãã»ã¼ã¸ãåãããããã§ãã...!!!
valueã«ãªã¹ãããã¤è¾æ¸ã®ãªã¹ã: DeepDiffã使ã
ãªã¹ãã®æ¯è¼ã¯ã大æµã¯sortedã¨assertCountEqualã§å¯è½ãã¨æãã¾ãã
ã¨ããããããã以ä¸è¤éãªæ¯è¼ããããªããããããã¹ãã®æ§æãæ¯è¼ã®ä»æ¹ãèãç´ããæ¹ããããã¨æãã¾ãã
ããããåé ã«ãæ¸ãã¾ããããAPIã®è¿ãå¤ãªã©ããå®éã«å©ãã¦ã¿ã¦ãã¨ã£ãå¤ããã®ã¾ã¾ãã¹ãã«ä½¿ãããã¨ããã·ã¼ã³ãæã ããã¾ãã
使ãæ¨ã¦ã®ã¹ã¯ãªããããã°ã¬ããªãããã«ä¿®æ£ããã¨ãã®ä¸æçãªãã¹ãã³ã¼ããä½ãæãªã©ã«ã¯ãèªåã¯ãã®ãããªassertãæ¸ããããªãã¾ãã
ãã®å ´åãããªã¹ãã®è¦ç´ ãè¾æ¸ããã¤ããè¾æ¸ã®valueã«ããªã¹ãããããããã®ãªã¹ãã®é çªãç¡è¦ãã¦è¦ç´ ãä¸è´ãã¦ããã確èªãããã±ã¼ã¹ãããã¾ãã
ä¾ãåºãã¨ããããªæãã§ãã
>>> dict_in_list1 [ {'name': 'Reimu', 'spells': ['Musouhuin', 'niju-kekkai']}, {'name': 'Marisa', 'spells': ['non-directional laser', 'star-dust reverie']}, {'name': 'Alice', 'spells': ['hourai-doll', 'shanghai-doll']} ] >>> dict_in_list2 [ {'name': 'Marisa', 'spells': ['star-dust reverie', 'non-directional laser']}, {'name': 'Reimu', 'spells': ['Musouhuin', 'niju-kekkai']}, {'name': 'Alice', 'spells': ['hourai-doll', 'shanghai-doll']} ]
ä¸ã®2ã¤ã®ãªã¹ãã¯ãè¦ç´ ã§ããdictã®é çªãå ¥ãæ¿ãã£ã¦ãã¾ãã
ããã«ãname: Marisaã®é ç®ãè¦ãã¨ãspellsè¦ç´ ã¯ãªã¹ããªã®ã§ãããä¸ã«æãåºããããã«é çªãéã«ãªã£ã¦ãã¾ãã
'spells': ['non-directional laser', 'star-dust reverie'] 'spells': ['star-dust reverie', 'non-directional laser']
ãããå«ããåä¸ã®ç©ã¨ãã¦å¤å®ãããã§ãã
ã¡ãªã¿ã«assertCountEqualã使ãã¨ã以ä¸ã®ããã«ç°ãªãè¦ç´ ã ã¨å¤å®ããã¦ãã¾ãã¾ãã
>>> case.assertCountEqual(dict_in_list1, dict_in_list2) AssertionError: Element counts were not equal: First has 1, Second has 0: {'name': 'Marisa', 'spells': ['non-directional laser', 'star-dust reverie']} First has 0, Second has 1: {'name': 'Marisa', 'spells': ['star-dust reverie', 'non-directional laser']}
ãã®ãããªã±ã¼ã¹ã§ãåããªãã¸ã§ã¯ãã ã¨ä¸çºã§å¤å®ã§ãããµã¼ããã¼ãã£è£½ã®ã©ã¤ãã©ãªãããã¾ãããããdeepdiffã§ãã
æ¬æ¥ãã£ã¨å¤æ©è½ãªã®ã§ãããä»åã¯ãã¹ãã¨ãã観ç¹ã®ã¿ããè¨è¿°ãã¾ã.
å°å ¥ã¯pipã§ç°¡åã«è¡ãã¾ã.
$ pip install deepdiff
ä»åã®ã±ã¼ã¹(ãªã¹ãé¨åã®é çªãç¡è¦ãã¦åä¸ããå¤å®)ã§ã®ä½¿ç¨ã¯ã以ä¸ã®ããã«ignore_order=True
ã¨ãã¦ãããªãã¾ãã
DeepDiff(dict_in_list1, dict_in_list2, ignore_order=True) {} # 空ã®deepdiff.diff.DeepDiffãªãã¸ã§ã¯ããè¿ã£ã¦ãã.
ãã¨ã¯åé ã§ç¤ºããããã«ãassertæãassertã¡ã½ããã§å¤å®ããã°OKã§ãã
ãªããDeepDiffã¯å·®åãããå ´åã«ã¯ãã©ã®ãã¼ã®ã©ã®è¦ç´ ããã©ããªãµãã«ç°ãªã£ã¦ãããã示ãã¦ããã¾ãã
>>> dict_in_list3 = [ {"name": "Marisa", "spells": ["star-dust reverie", "non-directional laser"]}, {"name": "Reimu", "spells": ["niju-kekkai"]}, ] >>> DeepDiff(dict_in_list1, dict_in_list3, ignore_order=True) { 'iterable_item_removed': { "root[0]['spells'][0]": 'Musouhuin', 'root[2]': { 'name': 'Alice', 'spells': ['hourai-doll', 'shanghai-doll'] } } }
dict_in_list3ã§åé¤ãããæ å ±ããé層æ å ±ã¨ã¨ãã«è¡¨ç¤ºããã¾ãã.
çµè«
- å¯è½ãªéãsortedã§ã½ã¼ããã¦æ¯è¼ãã.
- sortæ¡ä»¶ãè¤éã«ãªããªããassertCountEqualã¡ã½ããã®ä½¿ç¨ãæ¤è¨ãã.
- ãã£ã¨é£ããç¶æ³ã§ã¯DeepDiffãignore_order=Trueã¨ãã¦ä½¿ããã¨ãã§ãã.
ã¾ã¨ã
é çªã«ããããåãè¦ç´ ãæã¤ãªã¹ãã§ããããæ¤è¨¼ããæ¹æ³ã3ã¤ç´¹ä»ãã¾ããã
ãã¡ãããããããæ¯è¼ãã«ãããã®ãæ¯è¼ããã«æ¸ããã¹ããæ¸ãããªããã®æ¹ãããã§ãããã¾ãä¹±ç¨ããã¨ãè¿ã£ã¦èªã¿è¾ããã¹ãã«ãªã£ã¦ãã¾ãããããã¾ããã
ãããç¹å®ã®æèã§ã¯ãä»åç´¹ä»ãããããªæ¹æ³ã試ãã®ãé¸æè¢ã«å ¥ãã¦ãè¯ãã®ã§ã¯ãªãã§ãããã.
ä»ã«ãããæ¹æ³ãèªåãªããããããï¼ãªã©ã®ãæè¦ããã ããã¨å¬ããã§ãã