简体   繁体   中英

Most pythonic way of iterating list items into a nested dict

I have a problem and I want to determine whether my approach is sound. Here is the idea:

I would be creating a primary dict called zip_codes, of which respective zipcodes (from a list) were the names of each of the nested dicts. Each would have keys for "members", "offices", "members per office" It would look like this:

zips {
    90219: {
      "members": 120,
      "offices": 18,
      "membersperoffice": 28
    },
    90220: {
      "members": 423,
      "offices": 37,
      "membersperoffice": 16
    }
}

and so on and so forth.

I think I need to build the nested dicts, and then process several lists against conditionals, passing resulting values into the corresponding dicts on the fly (ie based on how many times a zip code exists in the list).

Is using nested dictionaries the most pythonic way of doing this? Is it cumbersome? Is there a better way?

Can someone drop me a hint about how to push key values into nested dicts from a loop? I've not been able to find a good resource describing what I'm trying to do (if this is, indeed, the best path).

Thanks.

:edit: a more specific example:

  1. determine how many instances of a zipcode are in list called membersperzip
  2. find corresponding nested dict with same name as zipcode, inside dict called zips
  3. pass value to corresponding key, called "members" (or whatever key)

:edit 2:

MadPhysicist requested I give code examples (I don't even know where to start with this one and I can't find examples. All I've been able to do thus far is:

area_dict = {}

area_dict = dict.fromkeys(all_areas, 0)  #make all of the zipscodes keys, add a zero in the first non-key index

dictkeys = list (area_dict.keys())

That gets me a dict with a bunch of zip codes as keys. I've discovered no way to iterate through a list and create nested dicts (yet). Hence the actual question.

Please don't dogpile me and do the usual stack overflow thing. This is not me asking anyone to do my homework. This is merely me asking someone to drop me a HINT.

:edit 3:

Ok. This is convoluted (my fault). Allow me to clarify further:

So, I have an example of what the nested dicts should look like. They'll start out empty, but I need to iterate through one of the zip code lists to create all the nested dicts... inside of zips.

This is a sample of the list that I want to use to create the nested dicts inside of the zips dict:

zips = [90272, 90049, 90401, 90402, 90403, 90404, 90291, 90292, 90290, 90094, 90066, 90025, 90064, 90073]

And this is what I want it to look like

zips {
    90272: {
      "members": ,
      "offices": ,
      "membersperoffice": 
    },
    90049: {
      "members": ,
      "offices": ,
      "membersperoffice": 
    }
}

.... etc, etc. ( creating a corresponding nested dict for each zipcode in the list)

After I achieve this, I have to iterate through several more zip code lists... and those would spit out the number of times a zip code appears in a given list, and then find the dict corresponding to the zip code in question, and append that value to the relevant key.

One I figure out the first part, I can figure this second part out on my own.

Thanks again. Sorry for any confusion.

You can do something like this:

all_areas = [90219, 90220]

zips = {zipcode: code_members(zipcode) for zipcode in all_areas}

def code_members(zipcode):
    if zipcode == 90219:
        return dict(members=120, offices=18, membersperoffice=28)
    return dict(members=423, offices=37, membersperoffice=16)

I think I need to build the nested dicts, and then process several lists against conditionals, passing resulting values into the corresponding dicts on the fly ( ie based on how many times a zip code exists in the list ).

Using the above approach, if a zipcode appears multiple times in the all_areas list, the resulting zip dictionary will only contain one instance of the zipcode .

Is using nested dictionaries the most pythonic way of doing this? Is it cumbersome? Is there a better way?

May I suggest making a simple object that represents the value of each zipcode . Something simple like:

Using dataclass:

@dataclass.dataclass
class ZipProperties(object):
    members: int
    offices: int
    membersperoffice: int

Using named tuple:

ZipProperties = collections.namedtuple('ZipProperties', ['members', 'offices', 'membersperoffice'])

You can then change the code_members function to this:

def code_members(zipcode):
    if zipcode == 90219:
        return ZipProperties(120, 18, 28)
    return ZipProperties(423, 37, 16)

Addressing your concrete example:

  1. determine how many instances of a zipcode are in list called membersperzip
  2. find corresponding nested dict with same name as zipcode, inside dict called zips
  3. pass value to corresponding key, called "members" (or whatever key)
membersperzip: typings.List[Tuple[int, int]] = [(90219, 54)]

for zip, members in membersperzip:
    for zipcode, props in zips.items():
        if zipcode == zip:
            props.members = members

I would suggest you to append it when you have the actual value instead of initializing dictionary with empty values for each key. You have list of keys and I do not see why you want to put all of them to the dictionary without having value in the first place.

zips = [90272, 90049, 90401, 90402, 90403, 90404, 90291, 90292, 90290, 90094, 90066, 90025, 90064, 90073]
zips_dict = {}
for a_zip in zips:
    if a_zip not in zips_dict:
        # Initialize proper value here for members etc.
        zips_dict[a_zip] = proper_value

If you insist to initialize dict with empty value for each keys, you could use this, which will also iterate through the list anyway but in python comprehension.

zips = [90272, 90049, 90401, 90402, 90403, 90404, 90291, 90292, 90290, 90094, 90066, 90025, 90064, 90073]
zips_dict = {
   x:{
       "members":None,
       "offices":None,
       "membersperoffice":None,
   } for x in zips
}

Hope this helps

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM