Last active
August 29, 2015 14:14
-
-
Save w495/37f3ab7a8550fc45fb48 to your computer and use it in GitHub Desktop.
Реализация `select sum(...) fom group by ...` на Python. На вход подается список словарей, и списки полей (всех, и по которым нужно суммировать).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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