Reputation: 595
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
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:
You can wrap that solution in a function by adding in the beggining:
def test_unique_values(dictionary: dict):
Upvotes: 2
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
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
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