Skip to content

Instantly share code, notes, and snippets.

@w495
Last active August 29, 2015 14:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save w495/37f3ab7a8550fc45fb48 to your computer and use it in GitHub Desktop.
Save w495/37f3ab7a8550fc45fb48 to your computer and use it in GitHub Desktop.
Реализация `select sum(...) fom group by ...` на Python. На вход подается список словарей, и списки полей (всех, и по которым нужно суммировать).
from itertools import groupby
def dlist_sum_group(
target_dlist,
groupby_field_list = [],
sum_field_list = [],
field_list = [],
convert = tolong,
):
return dlist_agregate_group(
agregate_function = sum,
target_dlist = target_dlist,
agregate_field_list = sum_field_list,
field_list = field_list,
convert = lambda x: tolong(x, 0)
)
def dlist_agregate_group(
agregate_function,
target_dlist,
groupby_field_list = [],
agregate_field_list = [],
field_list = [],
convert = lambda x: x
):
if(not groupby_field_list):
field_set = set(field_list)
field_set_for_sum = set(agregate_field_list)
field_set.difference_update(field_set_for_sum)
groupby_field_list = list(field_set)
def build_groupby_key_dict(item):
return {
field : item.get(field)
for field in groupby_field_list
}
target_dlist = sorted(
target_dlist,
key=build_groupby_key_dict
)
prefetch = [
(groupby_key_dict, list(for_agregate_generator))
for groupby_key_dict, for_agregate_generator in groupby(
target_dlist,
key=build_groupby_key_dict
)
]
target_dlist = [
dict(
groupby_key_dict.items()
+ [
(
field,
agregate_function(convert(fa_dict.get(field, 0))
for fa_dict in for_agregate_dlist)
)
for field in agregate_field_list
]
)
for groupby_key_dict, for_agregate_dlist in prefetch
]
return target_dlist
def tolong(a, default = None):
if(None == a):
return default
if isinstance(a, long):
return a
if isinstance(a, str) or isinstance(a, unicode):
if(not check_isdigit(a)):
return default
try:
return long(a)
except:
return default
return default
def check_isdigit(s):
if len(s) and s[0] in ('-', '+'):
return s[1:].isdigit()
return s.isdigit()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment