Need help with getting Key, Value out of dicts in lists

Peter Otten __peter__ at web.de
Sun Apr 9 04:15:51 EDT 2017


Kenton Brede wrote:

> This is an example of the data I'm working with.  The key/value pairs may
> come in any order. There are some keys like the 'Resource_group_id' key
> and the 'Name' key which will always be present, but other lists may have
> unique keys.
> 
> alist = [[{u'Value': 'shibboleth-prd', u'Key': 'Name'}, {u'Value': 'kvmu',
> u'Key': 'Billing'},
>             {u'Value': '20179204-181622543367489', u'Key':
> 'Resource_group_id'}],
>            [{u'Value': '20172857-152037106154311', u'Key':
> 'Resource_group_id'},
>             {u'Value': 'shibboleth-tst', u'Key': 'Name'}]]
> 
> What I want to do is something along the lines of:
> 
> for a in alist:
>     if a['Resource_group_id'] == '01234829-2041523815431':
>         print the Value of 'Name'
>         print the Value of 'Billing'
> 
> I've found I can do the following, to print the value of 'Name' but that
> only works if the 'Resource_group_id' key is the first key in the list and
> the 'Name' key is in the second slot.  If each list contained the same
> keys, I could probably sort the keys and use [num] to pull back values,
> but they don't.
> 
> for a in alist:
>     if a[0]['Key'] == 'Resource_group_id' and a[0]['Value'] ==
> '20172857-152037106154311':
>         print a[1]['Value']
> 
> There has to be a way to do this but I've been pounding away at this for
> hours.  Any help appreciated.  I'm new to Python and not a programmer, so
> go easy on me. :)

The easiest approach is to convert the inner list of dicts into one 
dictionary. Here's a way that ensures that duplicates are not overwritten 
silently:

def to_dict(pairs):
    result = {}
    for pair in pairs:
        key = pair["Key"]
        value = pair["Value"]
        if key in result:
            raise ValueError("Duplicate key {!r}".format(key))
        result[key] = value
    return result

Example:
>>> to_dict([{"Key": "foo", "Value": "bar"}, {"Key": "one", "Value": 
"two"}])
{'foo': 'bar', 'one': 'two'}

Now you can convert your data:

blist = [to_dict(pairs) for pairs in alist]

Then the rest of the code becomes straight-forward:

# linear lookup, you have to go through the whole list
# to find the matching items
for b in blist:
    if b["Resource_group_id"] == '20179204-181622543367489':
        print b["Name"]
        print b["Billing"]

If you are planning to do more than a few lookups and the lookup is always 
by resource group ID you can use a dict as the outer data structure, too:

from collections import defaultdict

# map ressource-group-ID to list of matching dicts
bdict =  defaultdict(list)

for pairs in alist:
    d = to_dict(pairs)
    bdict[d["Resource_group_id"]].append(d)

# constant-time lookup of a list containing all matching items 
for b in bdict["20179204-181622543367489"]:
    print b["Name"]
    print b["Billing"]





More information about the Python-list mailing list