如何判断我是否在子字典中有特定的唯一值?

时间:2016-06-23 00:46:59

标签: python python-2.7 python-3.x dictionary

dictionary = {'key01' : {'value_a': 1, 'value_b': 4, 'value_c': 1, 'value_d': 1},
            'key02' : {'value_a': 2, 'value_b': 5, 'value_c': 2, 'value_d': 6},
            'key03' : {'value_a': 3, 'value_b': 6, 'value_c': 2, 'value_d': 9}}

与其他value_a相比,每个value_a必须是唯一的 与其他value_b相比,每个value_b必须是唯一的 与其他value_c相比,每个value_c必须是唯一的 等...

即。如果dictionary['key01']['value_a']为1,则此值不会再次显示在dictionary['key02']['value_a']dictionary['key03']['value_a']中。

我需要为此写一个 pytest-assert

在示例中,由于dictionary['key02']['value_c']dictionary['key03']['value_c']相等,因此出现错误。

4 个答案:

答案 0 :(得分:2)

你走了:

dictionary = { 'key01': { 'value_a': 1, 'value_b': 4, 'value_c': 1, 'value_d': 1 },
               'key02': { 'value_a': 2, 'value_b': 5, 'value_c': 2, 'value_d': 6 },
               'key03': { 'value_a': 3, 'value_b': 6, 'value_c': 2, 'value_d': 9 } }

for key_first, key_second in itertools.combinations(dictionary, 2):
    for internal_key in dictionary[key_first].keys():
        if internal_key not in dictionary[key_second]:
            continue
        assert dictionary[key_first][internal_key] != dictionary[key_second][internal_key], \
            "Values in dictionary should be unique for the same keys!\n" + \
            "Invalid keys are " + key_first + " and " + key_second + "\n" + \
            "for values of " + internal_key

起初可能会让人感到困惑,但它的作用是:

  1. 浏览字典中的每个键,并将其值与其他每个键值进行比较(但不与其自身对应),
  2. 比较内部字典中所有键的值(如果它们都存在于两个键中),
  3. 如果任何键值相等,则抛出AssertionError。
  4. 您可以通过添加beggining:

    将该解决方案包装在函数中
    def test_unique_values(dictionary: dict):
    

答案 1 :(得分:2)

让我们概括一下并假设子句可能包含不同的键。然后,我们可以在value_1

中的所有值中找到不同的键(例如value_2dictionary,...)
value_keys = set.union(*(set(v) for v in dictionary.values()))

现在对于每个值键,包含多少个子词典?这就是我们希望看到的关键字有多少不同的值:

counts = {k: len([sub_dict for sub_dict in dictionary.values()]) 
          for k in value_keys}

现在在字典中找到每个值键的不同值的实际数量

distinct_counts = {k: len({sub_dict[k] 
                          for sub_dict in dictionary.values() 
                          if k in sub_dict}) 
                   for k in value_keys}

比较它们以找到不正确的:

errors = {k for k, v in distinct_counts.items() if v != counts[k]}

现在检查错误是否为空。

>>> print(errors)
{'value_c'}

答案 2 :(得分:1)

您可以将字典转换为数据框,然后检查每行的唯一值,我们可以检查行的长度和唯一值(set(row))的大小是否相同,如果不是,抛出异常:

import pandas as pd

df = pd.DataFrame(dictionary)

df
#           key01 key02 key03
# value_a     1     2     3
# value_b     4     5     6
# value_c     1     2     2
# value_d     1     6     9

def test(row):
    if row.size != len(set(row)):
        raise Exception("Test Failed!")

res = df.apply(test, axis = 1)

这将导致测试失败的例外。

答案 3 :(得分:0)

这是我提出的超长列表理解:

assrt( False not in [[False if list(set([dictionary[k][val] for k in  [key for key in dictionary.keys()]])) != [dictionary[k][val] for k in  [key for key in dictionary.keys()]] else True] for val in dictionary["key01"].keys()])

哪个更清楚:

for val in dictionary["key01"].keys():
    d = [dictionary[k][val] for k in  [key for key in dictionary.keys()]]
    assert(list(set(d)) == d)

d获取所有值并将它们放在一起(例如value_a key01key02 ...),然后测试唯一列表是否相等到目前的名单。