복붙노트

[PYTHON] 파이썬 : 한 사전이 다른 큰 사전의 하위 집합인지 확인하십시오

PYTHON

파이썬 : 한 사전이 다른 큰 사전의 하위 집합인지 확인하십시오

나는 임의의 수의 kwargs를 취하여 해당 kwargs를 포함하는 데이터베이스와 같은 목록 요소를 포함하는 목록을 반환하는 사용자 지정 필터 메서드를 작성하려고합니다.

예를 들어, d1 = { 'a': '2', 'b': '3'} 및 d2 = 같은 것으로 가정하십시오. d1 == d2 결과는 참입니다. 그러나 d2 = 같은 것을 더한 다른 것들을 생각 해보자. 내 방법은 d2가 d1인지 알 수 있어야하지만 파이썬은 사전을 사용하여이를 수행 할 수 없다.

문맥:

저는 Word 클래스를 가지고 있으며 각 객체는 word, definition, part_of_speech 등과 같은 속성을 가지고 있습니다. Word.objects.filter (word = 'jump', part_of_speech = 'verb-intransitive')와 같이 이러한 단어의 기본 목록에서 필터 메서드를 호출 할 수 있기를 원합니다. 나는이 키와 값을 동시에 관리하는 방법을 알 수 없다. 그러나 이것은 다른 사람들을 위해이 문맥 밖에서 더 큰 기능을 가질 수 있습니다.

해결법

  1. ==============================

    1.항목 쌍으로 변환하고 포함을 확인하십시오.

    항목 쌍으로 변환하고 포함을 확인하십시오.

    all(item in superset.items() for item in subset.items())
    

    최적화는 독자의 연습 과제로 남겨 둡니다.

  2. ==============================

    2.파이썬 3에서는 dict.items ()를 사용하여 dict 항목의 집합과 같은보기를 얻을 수 있습니다. 그런 다음 <= 연산자를 사용하여 한 뷰가 다른 뷰의 "하위 세트"인지 테스트 할 수 있습니다.

    파이썬 3에서는 dict.items ()를 사용하여 dict 항목의 집합과 같은보기를 얻을 수 있습니다. 그런 다음 <= 연산자를 사용하여 한 뷰가 다른 뷰의 "하위 세트"인지 테스트 할 수 있습니다.

    d1.items() <= d2.items()
    

    Python 2.7에서는 dict.viewitems ()를 사용하여 동일한 작업을 수행합니다.

    d1.viewitems() <= d2.viewitems()
    

    Python 2.6 이하에서는 all ()을 사용하는 것과 같은 다른 해결책이 필요합니다.

    all(key in d2 and d2[key] == d1[key] for key in d1)
    
  3. ==============================

    3.단위 테스트를 위해 필요한 사람을위한 노트 : 파이썬의 TestCase 클래스에는 assertDictContainsSubset () 메소드가있다.

    단위 테스트를 위해 필요한 사람을위한 노트 : 파이썬의 TestCase 클래스에는 assertDictContainsSubset () 메소드가있다.

    http://docs.python.org/2/library/unittest.html?highlight=assertdictcontainssubset#unittest.TestCase.assertDictContainsSubset

    그러나 3.2에서 더 이상 사용되지 않는 이유가 무엇인지, 어쩌면 대체 할 수 있을지도 모릅니다.

  4. ==============================

    4.키 및 값 확인 용도 : set (d1.items ()). issubset (set (d2.items ()))

    키 및 값 확인 용도 : set (d1.items ()). issubset (set (d2.items ()))

    키만 확인해야하는 경우 :         set (d1) .issubset (set (d2))

  5. ==============================

    5.완전성을 위해 다음 작업을 수행 할 수도 있습니다.

    완전성을 위해 다음 작업을 수행 할 수도 있습니다.

    def is_subdict(small, big):
        return dict(big, **small) == big
    

    그러나 나는 속도 (또는 그 부족) 또는 가독성 (또는 그 부족)과 관련하여 어떠한 주장도하지 않습니다.

  6. ==============================

    6.

    >>> d1 = {'a':'2', 'b':'3'}
    >>> d2 = {'a':'2', 'b':'3','c':'4'}
    >>> all((k in d2 and d2[k]==v) for k,v in d1.iteritems())
    True
    

    문맥:

    >>> d1 = {'a':'2', 'b':'3'}
    >>> d2 = {'a':'2', 'b':'3','c':'4'}
    >>> list(d1.iteritems())
    [('a', '2'), ('b', '3')]
    >>> [(k,v) for k,v in d1.iteritems()]
    [('a', '2'), ('b', '3')]
    >>> k,v = ('a','2')
    >>> k
    'a'
    >>> v
    '2'
    >>> k in d2
    True
    >>> d2[k]
    '2'
    >>> k in d2 and d2[k]==v
    True
    >>> [(k in d2 and d2[k]==v) for k,v in d1.iteritems()]
    [True, True]
    >>> ((k in d2 and d2[k]==v) for k,v in d1.iteritems())
    <generator object <genexpr> at 0x02A9D2B0>
    >>> ((k in d2 and d2[k]==v) for k,v in d1.iteritems()).next()
    True
    >>> all((k in d2 and d2[k]==v) for k,v in d1.iteritems())
    True
    >>>
    
  7. ==============================

    7.재귀 적으로이 일을하는 같은 목적을위한 내 함수 :

    재귀 적으로이 일을하는 같은 목적을위한 내 함수 :

    def dictMatch(patn, real):
        """does real dict match pattern?"""
        try:
            for pkey, pvalue in patn.iteritems():
                if type(pvalue) is dict:
                    result = dictMatch(pvalue, real[pkey])
                    assert result
                else:
                    assert real[pkey] == pvalue
                    result = True
        except (AssertionError, KeyError):
            result = False
        return result
    

    귀하의 예제에서, dictMatch (d1, d2)는 d2가 다른 것들을 가지고 있어도 True를 리턴해야하며, 더 낮은 레벨에도 적용됩니다 :

    d1 = {'a':'2', 'b':{3: 'iii'}}
    d2 = {'a':'2', 'b':{3: 'iii', 4: 'iv'},'c':'4'}
    
    dictMatch(d1, d2)   # True
    

    참고 사항 : if 형식 (pvalue)이 dict 절이며 피연산자가 더 넓은 범위 (예 : 해시 목록 등)에 적용되는 더 나은 솔루션이있을 수 있습니다. 또한 여기에는 재귀가 제한되지 않으므로 사용자의 책임하에 사용하십시오. ;)

  8. ==============================

    8.이 겉으로보기에는 간단한 문제는 100 % 신뢰할 수있는 솔루션을 찾기 위해 조사에서 두 시간의 비용이 들었으므로이 답변에서 내가 찾은 것을 문서화했습니다.

    이 겉으로보기에는 간단한 문제는 100 % 신뢰할 수있는 솔루션을 찾기 위해 조사에서 두 시간의 비용이 들었으므로이 답변에서 내가 찾은 것을 문서화했습니다.

  9. ==============================

    9.다음은 주어진 문제에 대한 일반적인 재귀 적 솔루션입니다.

    다음은 주어진 문제에 대한 일반적인 재귀 적 솔루션입니다.

    import traceback
    import unittest
    
    def is_subset(superset, subset):
        for key, value in subset.items():
            if key not in superset:
                return False
    
            if isinstance(value, dict):
                if not is_subset(superset[key], value):
                    return False
    
            elif isinstance(value, str):
                if value not in superset[key]:
                    return False
    
            elif isinstance(value, list):
                if not set(value) <= set(superset[key]):
                    return False
            elif isinstance(value, set):
                if not value <= superset[key]:
                    return False
    
            else:
                if not value == superset[key]:
                    return False
    
        return True
    
    
    class Foo(unittest.TestCase):
    
        def setUp(self):
            self.dct = {
                'a': 'hello world',
                'b': 12345,
                'c': 1.2345,
                'd': [1, 2, 3, 4, 5],
                'e': {1, 2, 3, 4, 5},
                'f': {
                    'a': 'hello world',
                    'b': 12345,
                    'c': 1.2345,
                    'd': [1, 2, 3, 4, 5],
                    'e': {1, 2, 3, 4, 5},
                    'g': False,
                    'h': None
                },
                'g': False,
                'h': None,
                'question': 'mcve',
                'metadata': {}
            }
    
        def tearDown(self):
            pass
    
        def check_true(self, superset, subset):
            return self.assertEqual(is_subset(superset, subset), True)
    
        def check_false(self, superset, subset):
            return self.assertEqual(is_subset(superset, subset), False)
    
        def test_simple_cases(self):
            self.check_true(self.dct, {'a': 'hello world'})
            self.check_true(self.dct, {'b': 12345})
            self.check_true(self.dct, {'c': 1.2345})
            self.check_true(self.dct, {'d': [1, 2, 3, 4, 5]})
            self.check_true(self.dct, {'e': {1, 2, 3, 4, 5}})
            self.check_true(self.dct, {'f': {
                'a': 'hello world',
                'b': 12345,
                'c': 1.2345,
                'd': [1, 2, 3, 4, 5],
                'e': {1, 2, 3, 4, 5},
            }})
            self.check_true(self.dct, {'g': False})
            self.check_true(self.dct, {'h': None})
    
        def test_tricky_cases(self):
            self.check_true(self.dct, {'a': 'hello'})
            self.check_true(self.dct, {'d': [1, 2, 3]})
            self.check_true(self.dct, {'e': {3, 4}})
            self.check_true(self.dct, {'f': {
                'a': 'hello world',
                'h': None
            }})
            self.check_false(
                self.dct, {'question': 'mcve', 'metadata': {'author': 'BPL'}})
            self.check_true(
                self.dct, {'question': 'mcve', 'metadata': {}})
            self.check_false(
                self.dct, {'question1': 'mcve', 'metadata': {}})
    
    if __name__ == "__main__":
        unittest.main()
    

    참고 : 원래 코드는 특정 경우에 실패 할 것이고, 수정에 대한 크레딧은 @ olivier-melançon으로갑니다.

  10. ==============================

    10.이 함수는 해시 가능하지 않은 값에 대해 작동합니다. 나는 또한 그것이 명확하고 읽기 쉽다고 생각한다.

    이 함수는 해시 가능하지 않은 값에 대해 작동합니다. 나는 또한 그것이 명확하고 읽기 쉽다고 생각한다.

    def isSubDict(subDict,dictionary):
        for key in subDict.keys():
            if (not key in dictionary) or (not subDict[key] == dictionary[key]):
                return False
        return True
    
    In [126]: isSubDict({1:2},{3:4})
    Out[126]: False
    
    In [127]: isSubDict({1:2},{1:2,3:4})
    Out[127]: True
    
    In [128]: isSubDict({1:{2:3}},{1:{2:3},3:4})
    Out[128]: True
    
    In [129]: isSubDict({1:{2:3}},{1:{2:4},3:4})
    Out[129]: False
    
  11. ==============================

    11.나는이 질문이 오래되었다는 것을 알고 있지만, 하나의 중첩 된 사전이 다른 중첩 된 사전의 일부인지 확인하기위한 나의 해결책이다. 해는 재귀 적입니다.

    나는이 질문이 오래되었다는 것을 알고 있지만, 하나의 중첩 된 사전이 다른 중첩 된 사전의 일부인지 확인하기위한 나의 해결책이다. 해는 재귀 적입니다.

    def compare_dicts(a, b):
        for key, value in a.items():
            if key in b:
                if isinstance(a[key], dict):
                    if not compare_dicts(a[key], b[key]):
                        return False
                elif value != b[key]:
                    return False
            else:
                return False
        return True
    
  12. from https://stackoverflow.com/questions/9323749/python-check-if-one-dictionary-is-a-subset-of-another-larger-dictionary by cc-by-sa and MIT license