42piratas
42piratas

Reputation: 595

How to assert if I have specific unique values in a subdictionary?

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}}

Each value_a must be unique in comparison with other value_a.
Each value_b must be unique in comparison with other value_b.
Each value_c must be unique in comparison with other value_c.
etc...

I.e. if dictionary['key01']['value_a'] is 1, this value CAN'T appear again in dictionary['key02']['value_a'] and dictionary['key03']['value_a'].

I need to write a pytest-assert for that!

In the example, there's a error since dictionary['key02']['value_c'] and dictionary['key03']['value_c'] are equal.

Upvotes: 1

Views: 950

Answers (4)

Jezor
Jezor

Reputation: 3426

Here you go:

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

It might be confusing at first, but what it does is:

  1. go through every key in the dictionary and compare it's value with every other keys value (but not with itself),
  2. compare values of all of the keys in the internal dictionary if they are present in both of them,
  3. if for any key the values are equal, throw AssertionError.

You can wrap that solution in a function by adding in the beggining:

def test_unique_values(dictionary: dict):

Upvotes: 2

Moon Cheesez
Moon Cheesez

Reputation: 2701

Here is a super long list comprehension I came up with:

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()])

Which would be clearer:

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 gets all the values and puts them together (e.g. value_a in key01, key02...), then, it tests if the unique list is equal to the current list.

Upvotes: 0

akuiper
akuiper

Reputation: 214977

You can convert the dictionary to a data frame and then check the unique values of each row for which we can check if the length of the row and the size of the unique values (set(row)) are the same, if not, throw an exception:

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)

This will throw an exception of failed test.

Upvotes: 1

donkopotamus
donkopotamus

Reputation: 23186

Lets generalise it and assume that the subdictionaries may contain different keys. Then lets find the distinct keys (eg value_1, value_2, ...) across all of the values in dictionary

value_keys = set.union(*(set(v) for v in dictionary.values()))

Now for each value key, how many sub dictionaries contain it? That's how many distinct values we will hope to see for that key:

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

Now find the actual number of distinct values for each value key among the dictionaries

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

Compare them to find the incorrect ones:

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

Now check if errors is empty.

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

Upvotes: 2

Related Questions