2016-06-23 12 views
1
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と比較してユニークでなければなりません。
等...サブ辞書に特定の一意の値がある場合、どのようにアサートするのですか?

I.e. dictionary['key01']['value_a']が1の場合、この値はdictionary['key02']['value_a']dictionary['key03']['value_a']に再び表示されません。

これはpytest-assertと書く必要があります。

この例では、dictionary['key02']['value_c']dictionary['key03']['value_c']が等しいため、エラーがあります。

+0

つまり、1行にする必要がありますか?最善の方法は、その複雑さのために関数を使用することですが、まだ実行することができます。 –

答えて

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. 値が等しい場合、thro w AssertionError。
あなたはbegginingに追加することで機能でそのソリューションをラップすることができます

:あなたは、データフレームに辞書を変換し、そのために私たちがチェックすることができ、各列の一意の値を確認することができます

def test_unique_values(dictionary: dict): 
+0

素晴らしいソリューション、@ジェゾー!しかし、それは3つのキーの辞書でのみ機能します。 – anquadros

+0

いいえ、任意の数のキーで動作します。コードにはどこにも「3」のマジックナンバーがないことに注意してください。内部辞書の特定のキーのみをチェックしたい場合は、質問を更新し、その要件を追加してください。 – Jezor

+0

itertools.combinations(辞書、2)のk1、k2に対して、作業を半分にし、 'if ...'チェックを削除する単純なループは... – donkopotamus

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) 

これは失敗したテストの例外をスローします。

+0

ありがとう@Psidom! – anquadros

+0

恐ろしい解決! – anquadros

+0

それは "フィクスチャの行が見つかりません"を返しています – anquadros

2

これを一般化して、サブディクショナリに異なるキーが含まれている可能性があるとします。そして、それぞれの値のキーのための今すぐdictionary

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

の値のすべての間で個別の鍵を(例えばvalue_1value_2、...)を見つけることができます、それはどのように多くのサブ辞書が含まれていますか?

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

間違ったものを見つけるためにそれらを比較

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

今すぐ辞書の中で、各値のキーのための個別値の実際の数を見つける:それは私たちがそのキーを参照したいと考えていますどのように多くの個別の値です:

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

エラーが空であるかどうかを確認します。ここで

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

thanks @donkopotamus! – anquadros

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_akey01key02 ...)、一意のリストが現在のリストと等しいかどうかをテストします。

関連する問題