在嵌套字典

时间:2017-03-14 04:44:05

标签: python dictionary

我有一个这种形式的字典:

d = {
  'A': {
     'a1': {3},
     'a2': {2},
     'a3': {1},
   },
  'B': {
     'b1': {1},
   },  
  'C': {
     'c1': {2, 3},
   }
}

我还有其他类似形式的词典,但我的目标是确定数字1,2,3是否存在于键A, B, and C的值中。

在上面的字典d中,答案是True,因为我有:

A.a2包含2

B.b1包含1

C.c1包含3

所以在字典d中我有值1,2,3

保证只有3个键A, B, C和3个嵌套键a1, a2, a3(b1,c1相同)。此外,每组中唯一可能的值为1,2,3

我可以迭代字典的所有排列,但我认为不会那么有效。想知道在A,B,C

的值内是否存在更明智的方式来确认1,2,3

以下是其他词典的一些示例输出:

VALID

  • A.a2 - > 2,B.b1 - > 1,C.c1 - > 3

    {       ' A':{          ' a1':{3},          ' a2':{2},          ' a3':{1},        },       ' B':{          ' b1':{1},        },
          ' C':{          ' c1':{2,3},        }     }

INVALID

  • 我们有B.b1 - > 1,C.c1 - > 2

  • 我们需要A.a3 - > 3

OR

仍然无效

  • 我们有B.b1 - > 1,C.c1 - > 3

  • 我们需要A.a3 - > 2

    {   ' A':{      ' a3':{1},    },   ' B':{      ' b1':{1},    },
      ' C':{      ' c1':{2,3},      ' c2':{1}    } }

VALID

  • 我们有B.b1 - > 1,A.a2 - > 2,C.c1 - > 3

  • 我们在每个第一级Key中都有1,2,3个序列!

    {   ' A':{      ' a2':{2}    },   ' B':{      ' b1':{1},    },
      ' C':{      ' c1':{2,3},    } }

3 个答案:

答案 0 :(得分:1)

这是一个生成器,它解开A B和C的嵌套子句: 然后检查A B和C内容之间的所有联合,其元素至少与参与的子区域一样多。

def unravel_nested(d):
    for v in d.values():
        if isinstance(v, dict):
             yield from v.values()
        else:
             yield v

content = [functools.reduce(set.union, unravel_nested(d[X])) for X in 'ABC']
all(len(functools.reduce(set.union, comb)) >= k for k in range(1,4) for comb in itertools.combinations(content, k))
# True

答案 1 :(得分:1)

这是我将如何做到的。我知道我可以删除字典(好),但我认为这对于学习是好的:

d = {
  'A': {
     'a1': [3],
     'a2': [2],
     'a3': [1]
   },
  'B': {
     'b1': [1]
   },  
  'C': {
     'c1': [2, 3]
   }
}

def checkDictionary(di):
    good = {1:False,2:False,3:False}
    for key in di:
        for key2 in di[key]:
            for item in di[key][key2]:
                if item in good:
                    good[item] = True
    return good[1] and good[2] and good[3]

print(checkDictionary(d))

答案 2 :(得分:1)

>>> import itertools as it
>>> d
{'A': {'a1': set([3]), 'a3': set([1]), 'a2': set([2])}, 'C': {'c1': set([2, 3])}, 'B': {'b1': set([1])}}

>>> #iterate every key and vaue in dict
>>> [v for k,v in d.iteritems()]
[{'a1': set([3]), 'a3': set([1]), 'a2': set([2])}, {'c1': set([2, 3])}, {'b1': set([1])}]

>>> #iterate through every subdict
>>> [[value for key,value in v.iteritems()] for k,v in d.iteritems()]
[[set([3]), set([1]), set([2])], [set([2, 3])], [set([1])]]

>>> #join list of sets to a single list using itertools chain()
>>> #convert the iterools object to list
>>> [list(it.chain.from_iterable([value for key,value in v.iteritems()])) for k,v in d.iteritems()]
[[3, 1, 2], [2, 3], [1]]

>>> #sort every items in sublist
>>> [sorted(it.chain.from_iterable([value for key,value in v.iteritems()])) for k,v in d.iteritems()]
[[1, 2, 3], [2, 3], [1]]

>>> #sort all items in list
>>> sorted([sorted(it.chain.from_iterable([value for key,value in v.iteritems()])) for k,v in d.iteritems()])
[[1], [1, 2, 3], [2, 3]]

>>> #enumerate and check if each element in check([1,2,3]) is present in each index of obtained list
>>> [i for index,i in enumerate(sorted([sorted(it.chain.from_iterable([value for key,value in v.iteritems()])) for k,v in d.iteritems()])) if check[index] in i]
[[1], [1, 2, 3], [2, 3]]

是你需要的!

简化列表理解以便更好地理解,

>>> import itertools as it
>>> check = [1, 2, 3]
>>> d={'A': {'a1': set([3]), 'a3': set([1]), 'a2': set([2])}, 'C': {'c1': set([2, 3])}, 'B': {'b1': set([1])}}
>>> True if len([i for ind,i in enumerate(sorted([sorted(it.chain.from_iterable([value for key,value in v.iteritems()])) for k,v in d.iteritems()])) if check[ind] in i])==len(check) else False
True
>>> d={'A': {'a1': set([3]), 'a3': set([1])}, 'C': {'c1': set([1])}, 'B': {'b1': set([1])}}
>>> True if len([i for index,i in enumerate(sorted([sorted(it.chain.from_iterable([value for key,value in v.iteritems()])) for k,v in d.iteritems()])) if check[index] in i])==len(check) else False
False

现在将此结果的len与check的结果进行比较。如果它们相等,则为True,否则为False。

说以下内容应该给出所需的结果,

pytest <filename>.py arg1