Вот обновленная версия моего ответа, в котором листья древовидная структура данных теперь отличается f в том числе и в остальном. Вместо того, чтобы дерево было строго dict
-of-nested-dict
s, «листья» на каждой ветви теперь являются экземплярами другого подкласса dict
с именем collections.Counter
, которые полезны для подсчета количества раз, когда происходит каждый из их ключей. Я сделал это из-за вашего ответа на мой вопрос о том, что должно произойти, если последняя часть каждой строки была чем-то отличным от ":pass"
(что было «мы должны положить новый счет для этого ключа»).
Вложенных словари часто называют Tree
структур данных и могут быть определены рекурсивно — корень словарь, как ветвь. Ниже используется подкласс dict
вместо простого dict
, потому что он упрощает их создание, так как вам не требуется специальный случай создания первой ветви следующего уровня вниз (за исключением того, что я все еще делаю, добавляя «листья», потому что они другой подкласс, collections.Counter
).
from collections import Counter
import re
# (optional) trick that redefines Counter subclass to print like a regular dict
class Counter(Counter):
def __repr__(self):
return dict(self).__repr__()
# borrowed from answer @ http://stackoverflow.com/a/19829714/355230
class Tree(dict):
def __missing__(self, key):
value = self[key] = type(self)()
return value
# some functions based on answer @ http://stackoverflow.com/a/14692747/355230
def nested_dict_get(nested_dict, keys):
return reduce(lambda d, k: d[k], keys, nested_dict)
def nested_dict_set(nested_dict, keys, value):
nested_dict_get(nested_dict, keys[:-1])[keys[-1]] = value
def nested_dict_update_count(nested_dict, keys):
if nested_dict_get(nested_dict, keys[:-1]): # update existing Counter
nested_dict_get(nested_dict, keys[:-1]).update([keys[-1]])
else: # create a new Counter
nested_dict_set(nested_dict, keys[:-1], Counter([keys[-1]]))
d = Tree()
pat = re.compile(r'[a-zA-z]+')
with open('abc.txt') as file:
for line in file:
nested_dict_update_count(d, [w for w in pat.findall(line.rstrip())])
print d # prints like a regular dict
Для проверки возможности листа подсчета пересмотренного кода, я использовал следующий файл тест, который включает в себя ту же линию дважды, один раз заканчивается снова :pass
и еще заканчивающийся в :fail
.
Expanded abc.txt
тестовый файл:
abc/pqr/lmn/xyz:pass
abc/pqr/lmn/bcd:pass
abc/pqr/lmn/xyz:fail
abc/pqr/lmn/xyz:pass
Выход:
{'abc': {'pqr': {'lmn': {'bcd': {'pass': 1}, 'xyz': {'fail': 1, 'pass': 2}}}}}
Пожалуйста, дайте мне знать, если это правильная интерпретация Вашего комментария по поводу подсчета последнее слово в каждой строке.
извините. Я новичок в python, но каково будет решение для этого вывода. – sachin27
есть. простите за это. – sachin27
Что делать, если последняя часть каждой строки не является «: pass»? – martineau