Hung Dinh via plug on 3 Jul 2021 13:38:39 -0700


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: [PLUG] Python nested dict data structure


I would suggest the toolz library - https://toolz.readthedocs.io/en/latest/_modules/toolz/dicttoolz.html
There's useful functions in there for handling high order dictionary operations. Will look very familiar if you are coming from a functional background.

For example, if I would do something like the original script, it would look something like:

from toolz.dicttoolz import assoc_in, update_in
dict = {}
company = 'Acme Inc'
dict = assoc_in(dict, [company, 'region'], 'US') # note: it's immutable, so a new dict is created
dict = update_in(dict, [company, 'counter'], lambda x: (x or 0) + 1)   # x or 1 because x will be None
dict = update_in(dict, [company, 'counter'], lambda x: (x or 0) + 2)
print(dict)

On Fri, Jul 2, 2021 at 3:51 PM JP Vossen via plug <plug@lists.phillylinux.org> wrote:
If I want to read multiple files, and build a data structure like this by adding different keys and values at different times, and/or incrementing an existing numerical value:
```
{'Acme Inc': {'region': 'US', 'counter': 3}}
```

In Perl, but using Pythonic syntax, this would auto-instantiate and Just Work:
```
dict = {}
company = 'Acme Inc'
dict[company]['region']   = 'US'
dict[company]['counter'] += ave
```

Clean, and simple...except that Perl's syntax for nested data structures is virtually unreadable and really hard to write, for me at least.  Overall I'm liking Python, but there are some things, like this, that are hurting my head.

In Python it's really easy to create that structure at one time, but that is NOT how most of my use-cases work.  I'm always pulling fields out of 2-3 different files and building a data structure in pieces over time.  Like company and region are in 1 file, and a whole bunch of records containing something I want to count are in another file(s), with the 'company' key to link them.

This works in Python 3 and 2 (sad to say I still have old nodes with only Python2):
```
#!/usr/bin/env python3
# dict.py--do I REALLY have to do all this crap just for NESTED dicts!?

dict = {}

# Add Nested Key/Value pair to dict
def add_nstkv(dict, key, subkey, value):
     if key not in dict:         # Key must exist or error
         dict[key] = {}          # Create empty sub-dict
     dict[key][subkey] = value   # Add value

# Add/inc_nstkv a value in a nested dict
def inc_nstkv(dict, key, subkey, value):
     if key not in dict:              # Parent key must exist or error
         dict[key] = {}               # Create empty sub-dict
     if subkey not in dict[key]:      # Subkey must exist or error
         dict[key][subkey]  = value   # Add value
     else:
         dict[key][subkey] += value   # inc_nstkv

company = 'Acme Inc'
add_nstkv(dict, company, 'region', 'US') # Does: dict[company]['region']   = val
inc_nstkv(dict, company, 'counter', 1)   # Does: dict[company]['counter'] += val
inc_nstkv(dict, company, 'counter', 2)
print(dict)
```

Output:
```
$ ./dict.py
{'Acme Inc': {'region': 'US', 'counter': 3}}
```

I've tried `dict = defaultdict()` and `dict = defaultdict(int)` but both fail since I have mixed string and int values.  I've tried all kinds of other crazy stuff and nothing else worked either.  Most Google results are too-trivial `d[k] = v` and don't help with nested structs.

Do I *really* have to write all that extra code every time I want to do something this simple?  Or am I missing something?

Later,
JP
--  -------------------------------------------------------------------
JP Vossen, CISSP | http://www.jpsdomain.org/ | http://bashcookbook.com/
___________________________________________________________________________
Philadelphia Linux Users Group         --        http://www.phillylinux.org
Announcements - http://lists.phillylinux.org/mailman/listinfo/plug-announce
General Discussion  --   http://lists.phillylinux.org/mailman/listinfo/plug
___________________________________________________________________________
Philadelphia Linux Users Group         --        http://www.phillylinux.org
Announcements - http://lists.phillylinux.org/mailman/listinfo/plug-announce
General Discussion  --   http://lists.phillylinux.org/mailman/listinfo/plug