Here's an updated version of my answer in which leaves of the tree data-structure are now different from those in rest of it. Instead of the tree being strictly a dict
-of-nested-dict
s, the "leaves" on each branch are now instances of a different subclass of dict
named collections.Counter
which are useful for counting the number of times each of
their keys occur. I did this because of your response to my question about what should happen if the last part of each line was something other than ":pass"
[which was "we have to put new count for that key"].
Nested dictionaries are often called Tree
data-structures and can be defined recursively — the root is a dictionary as are the branches. The following uses a dict
subclass instead of a plain dict
because it makes constructing them easier since you don't
need to special case the creation of the first branch of next level down [except I still do when adding the "leaves" because they are a different subclass, collections.Counter
].
from collections import Counter
from functools import reduce
import re
# [Optional] trick to make Counter subclass print like a regular dict.
class Counter[Counter]:
def __repr__[self]:
return dict[self].__repr__[]
# Borrowed from answer @ //stackoverflow.com/a/19829714/355230
class Tree[dict]:
def __missing__[self, key]:
value = self[key] = type[self][]
return value
# Utility functions based on answer @ //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]:
counter = nested_dict_get[nested_dict, keys[:-1]]
if counter: # Update existing Counter.
counter.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.
To test the leaf-counting capabilities of the revised code, I used the following test file which includes the same line twice, once ending again with :pass
and another ending in :fail
.
Expanded abc.txt
test file:
abc/pqr/lmn/xyz:pass
abc/pqr/lmn/bcd:pass
abc/pqr/lmn/xyz:fail
abc/pqr/lmn/xyz:pass
Output:
{'abc': {'pqr': {'lmn': {'bcd': {'pass': 1}, 'xyz': {'fail': 1, 'pass': 2}}}}}
Prerequisite – Python dictionary
A Dictionary in Python works similar to the Dictionary in the real world. Keys of a Dictionary must be unique and of immutable data type such as Strings, Integers and tuples, but the key-values can be repeated and be of any type.
Nested Dictionary: Nesting Dictionary means putting a dictionary inside another dictionary. Nesting is of
great use as the kind of information we can model in programs is expanded greatly.
Python3
nested_dict
=
{
'dict1'
: {
'key_A'
:
'value_A'
},
'dict2'
: {
'key_B'
:
'value_B'
}}
Python3
Dict
=
{
1
:
'Geeks'
,
2
:
'For'
,
3
: {
'A'
:
'Welcome'
,
'B'
:
'To'
,
'C'
:
'Geeks'
}}
Creating a Nested Dictionary
In Python, a Nested dictionary can be created by placing the comma-separated dictionaries enclosed within braces.
Python3
Dict
=
{
'Dict1'
: { },
'Dict2'
: { }}
print
["Nested dictionary
1
-
"]
print
[
Dict
]
Dict
=
{
'Dict1'
: {
'name'
:
'Ali'
,
'age'
:
'19'
},
'Dict2'
: {
'name'
:
'Bob'
,
'age'
:
'25'
}}
print
["\nNested dictionary
2
-
"]
print
[
Dict
]
Dict
=
{
'Dict1'
: {
1
:
'G'
,
2
:
'F'
,
3
:
'G'
},
'Dict2'
: {
'Name'
:
'Geeks'
,
1
: [
1
,
2
]} }
print
["\nNested dictionary
3
-
"]
print
[
Dict
]
Output:
Nested dictionary 1- {'Dict1': {}, 'Dict2': {}} Nested dictionary 2- {'Dict1': {'name': 'Ali', 'age': '19'}, 'Dict2': {'name': 'Bob', 'age': '25'}} Nested dictionary 3- {'Dict1': {1: 'G', 2: 'F', 3: 'G'}, 'Dict2': {1: [1, 2], 'Name': 'Geeks'}}
Adding elements to a Nested Dictionary
Addition of elements to a nested Dictionary can be
done in multiple ways. One way to add a dictionary in the Nested dictionary is to add values one be one, Nested_dict[dict][key] = ‘value’. Another way is to add the whole dictionary in one go, Nested_dict[dict] = { ‘key’: ‘value’}.
Python3
Dict
=
{ }
print
["Initial nested dictionary:
-
"]
print
[
Dict
]
Dict
[
'Dict1'
]
=
{}
Dict
[
'Dict1'
][
'name'
]
=
'Bob'
Dict
[
'Dict1'
][
'age'
]
=
21
print
["\nAfter adding dictionary Dict1"]
print
[
Dict
]
Dict
[
'Dict2'
]
=
{
'name'
:
'Cara'
,
'age'
:
25
}
print
["\nAfter adding dictionary Dict1"]
print
[
Dict
]
Output:
Initial nested dictionary:- {} After adding dictionary Dict1 {'Dict1': {'age': 21, 'name': 'Bob'}} After adding dictionary Dict1 {'Dict1': {'age': 21, 'name': 'Bob'}, 'Dict2': {'age': 25, 'name': 'Cara'}}
Access elements of a Nested Dictionary
In order to access the value of any key in nested
dictionary, use indexing [] syntax.
Python3
Dict
=
{
'Dict1'
: {
'name'
:
'Ali'
,
'age'
:
'19'
},
'Dict2'
: {
'name'
:
'Bob'
,
'age'
:
'25'
}}
print
[
Dict
[
'Dict1'
][
'name'
]]
print
[
Dict
[
'Dict2'
][
'age'
]]
Output:
Ali 25
Deleting dictionaries from a Nested Dictionary
Deletion of dictionaries from a nested dictionary can be done either by using del keyword or by using pop[] function.
Python3
Dict
=
{
'Dict1'
: {
'name'
:
'Ali'
,
'age'
:
19
},
'Dict2'
: {
'name'
:
'Bob'
,
'age'
:
21
}}
print
["Initial nested dictionary:
-
"]
print
[
Dict
]
print
["\nDeleting Dict2:
-
"]
del
Dict
[
'Dict2'
]
print
[
Dict
]
print
["\nDeleting Dict1:
-
"]
Dict
.pop[
'Dict1'
]
print
[
Dict
]
Output:
Initial nested dictionary:- {'Dict2': {'name': 'Bob', 'age': 21}, 'Dict1': {'name': 'Ali', 'age': 19}} Deleting Dict2:- {'Dict1': {'name': 'Ali', 'age': 19}} Deleting Dict1:- {}