I've got a list of objects which will number somewhere between the thousands & tens of thousands. These objects could be thought of as people which I'm looking to rank based on a score they have.
So first of all they're split into groups by age, then gender etc. At each point a ranking is provided corresponding to that age/gender category. The fields on the objects are age_group and gender. So you'd first collect everybody that's got the 30-39 age group, then all the men (M) and all women (W) from that age group.
Creating a new list at each of these points is very memory intensive so I'm attempting to use a generator & itertools to group using the original list. So I've got a function to do that;
def group_standings(_standings, field):
""" sort list of standings by a given field """
getter = operator.attrgetter(field)
for k, g in itertools.groupby(_standings, getter):
yield list(g)
def calculate_positions(standings):
"""
sort standings by age_group then gender & set position based on point value
"""
for age_group in group_standings(standings, 'age_group'):
for gender_group in group_standings(age_group, 'gender'):
set_positions(
standings=gender_group,
point_field='points',
position_field='position',
)
For set_positions to function correctly it needs the whole group so that it can sort by the point_field value then set the position_field value.
Debugging the generator, groupby isn't collecting all objects matching the key as I'd expected. The output is something like;
DEBUG generating k 30-39
DEBUG generating g [<Standing object at 0x7fc86fedbe10>, <Standing object at 0x7fc86fedbe50>, <Standing object at 0x7fc86fedbe90>]
DEBUG generating k 20-29
DEBUG generating g [<Standing object at 0x7fc86fedbed0>]
DEBUG generating k 30-39
DEBUG generating g [<Standing object at 0x7fc86fedbf10>]
DEBUG generating k 20-29
DEBUG generating g [<Standing object at 0x7fc86fedbf50>, <Standing object at 0x7fc86fedbf90>, <Standing object at 0x7fc86fedbfd0>, <Standing object at 0x7fc856ecc050>, <Standing object at 0x7fc856ecc090>, <Standing object at 0x7fc856ecc0d0>, <Standing object at 0x7fc856ecc110>, <Standing object at 0x7fc856ecc150>, <Standing object at 0x7fc856ecc190>, <Standing object at 0x7fc856ecc1d0>]
To confirm, for set_positions to function, the list provided by the generator would need to contain all objects in the 20-29 age group, but as above, objects from that group are being found on multiple iterations of the list.