Я просто рассмотрю вопрос "Как часто значение появляется при заданном ключе в словаре", поскольку вы сказали, что "Как часто значение появляется в словаре в целом", легко определить.
Если вы просто хотите найти относительную частоту значения для данного ключа, это легко получить с помощью dict
из Counter
объектов:
from collections import Counter
rule = {'a': ['b', 'd'], 'b': ['b', 'c'], 'c': ['a']}
freq = {k: Counter(v) for k, v in rule.items()}
… что дает вам freq
вот так:
{
'a': Counter({'b': 1, 'd': 1}),
'b': Counter({'b': 1, 'c': 1}),
'c': Counter({'a': 1})
}
… так что вы можете получить относительную частоту 'a'
, учитывая ключ 'c'
, например:
>>> freq['c']['a']
1
Поскольку Counter
объекты возвращают 0 для несуществующих ключей, вы также получите нулевые частоты, как и следовало ожидать:
>>> freq['a']['c']
0
Если вам нужен список из 3-х кортежей, как указано в вашем вопросе, вы можете получить это с небольшой дополнительной работой. Вот функция для этого:
def triples(rule):
freq = {k: Counter(v) for k, v in rule.items()}
all_values = sorted(set().union(*rule.values()))
sorted_keys = sorted(rule)
return [(v, k, freq[k][v]) for v in all_values for k in sorted_keys]
Единственное, что, на мой взгляд, не может быть самоочевидным, это строка all_values = ...
, которая:
- создает пустое
set()
- создает
union()
этого набора со всеми отдельными элементами списков в rule.values()
(обратите внимание на использование оператора unpacking *
)
- преобразует результат в список
sorted()
.
Если у вас все еще есть оригинальный текст, вы можете избежать всей этой работы, например, используя all_values = sorted(set(original_text))
вместо.
Вот оно в действии:
>>> triples({'a': ['b', 'd'], 'b': ['b', 'c'], 'c': ['a']})
[
('a', 'a', 0), ('a', 'b', 0), ('a', 'c', 1),
('b', 'a', 1), ('b', 'b', 1), ('b', 'c', 0),
('c', 'a', 0), ('c', 'b', 1), ('c', 'c', 0),
('d', 'a', 1), ('d', 'b', 0), ('d', 'c', 0)
]