Will via plug on 2 Jul 2021 17:35:09 -0700


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

Re: [PLUG] Python nested dict data structure


Going off of what Carlos was saying. Is this what you're looking for? As long as you make sure each level is either a dict() or list(), you should be easy. 

```
>>> import json
>>> comp = dict()
>>> comp['Acme'] = dict()
>>> comp['Giant'] = dict()
>>> comp['Acme']['Lehigh'] = 0
>>> comp['Acme']['Bucks'] = 0
>>> comp['Giant']['Lehigh'] = 0
>>> comp['Giant']['Bucks'] = 0
>>> comp['Acme']['Lehigh'] += 1
>>> comp['Acme']['Bucks'] += 4
>>> comp['Giant']['Lehigh'] += 5
>>> comp['Giant']['Bucks'] += 3
>>> print(json.dumps(comp, indent=2, sort_keys=True))
{
  "Acme": {
    "Bucks": 4,
    "Lehigh": 1
  },
  "Giant": {
    "Bucks": 3,
    "Lehigh": 5
  }
}
```

However... to make the exact json as listed above in python: 
```
>>> jpEx = dict()
>>> jpEx['Acme Inc'] = list()
>>> jpEx['Acme Inc'].append(dict())
>>> jpEx['Acme Inc'][0]['region'] = "US"
>>> jpEx['Acme Inc'][0]['counter'] = 2       # Sets the value initially 
>>> jpEx['Acme Inc'][0]['counter'] += 1     # Increments in python 
>>> print(json.dumps(jpEx, indent=2, sort_keys=True))
{
  "Acme Inc": [
    {
      "counter": 3,
      "region": "US"
    }
  ]
}
```

-Will C

On Fri, Jul 2, 2021 at 5:19 PM Carlos M. Fernández via plug <plug@lists.phillylinux.org> wrote:
What prevents you from doing this?:

>>> d = dict()
>>> d
{}
>>> company = "Acme, Inc."
>>> company
'Acme, Inc.'
>>> d[company] = {"region": "US", "counter": 1}
>>> d
{'Acme, Inc.': {'region': 'US', 'counter': 1}}
>>> d[company]["counter"] += 1
>>> d
{'Acme, Inc.': {'region': 'US', 'counter': 2}}
>>>


Best regards,
//CMFM


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
___________________________________________________________________________
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