我想对按范围分组的键的值求和
[
{'scope': u'internal', 'invoiced': 1000, 'initial_boq': 2800}
{'scope': u'internal', 'invoiced': 2000, 'initial_boq': 1000}
{'scope': u'internal', 'invoiced': 2000, 'initial_boq': 500}
{'scope': u'external', 'invoiced': 500, 'initial_boq': 1800}
{'scope': u'external', 'invoiced': 150, 'initial_boq': 200}
{'scope': u'both', 'invoiced': 5000, 'initial_boq': 7000}
]
我们如何获得dict对范围进行分组的键之和:
预期输出
[
{'scope': u'internal', 'invoiced': 5000, 'initial_boq': 4300},
{'scope': u'external', 'invoiced': 650, 'initial_boq': 2000},
{'scope': u'both', 'invoiced': 5000, 'initial_boq': 7000}
]
请让我知道如何实现相同的目标
答案 0 :(得分:1)
由于您没有提供任何关于先前尝试的信息,因此我假设这个问题是关于从何开始的。
我要寻找的第一件事是使解决问题变得简单的数据结构。在这种情况下,我将创建一个求和字典:
sums = {
'internal': {'invoiced': …, 'initial_boq': …},
# …
}
特别适用于此的是defaultdict:
from collections import defaultdict
sums = defaultdict(lamdba: defaultdict(lambda:0))
使用此定义,您可以像这样添加值:
sums['internal']['invoiced'] += one_value
答案 1 :(得分:0)
您可以使用itertools.groupby
,就像这样。带有附加功能可以汇总分组的项目。
from itertools import groupby
from operator import itemgetter
d = [
{'scope': u'internal', 'invoiced': 1000, 'initial_boq': 2800},
{'scope': u'internal', 'invoiced': 2000, 'initial_boq': 1000},
{'scope': u'internal', 'invoiced': 2000, 'initial_boq': 500},
{'scope': u'external', 'invoiced': 500, 'initial_boq': 1800},
{'scope': u'external', 'invoiced': 150, 'initial_boq': 200},
{'scope': u'both', 'invoiced': 5000, 'initial_boq': 7000},
]
def getsummed(scope, elems):
d = {'scope': scope, 'invoiced': 0, 'initial_boq': 0}
for e in elems:
d['invoiced'] += e['invoiced']
d['initial_boq'] += e['initial_boq']
return d
def sortedgroupby(iterable, key):
return groupby(sorted(iterable, key=key), key=key)
print([getsummed(gpr, groups) for gpr, groups in sortedgroupby(d, key=itemgetter('scope'))])
结果是
[{'scope': 'internal', 'invoiced': 5000, 'initial_boq': 4300}, {'scope': 'external', 'invoiced': 650, 'initial_boq': 2000}, {'scope': 'both', 'invoiced': 5000, 'initial_boq': 7000}]
答案 2 :(得分:0)
list1 = [
{'scope': u'internal', 'invoiced': 1000, 'initial_boq': 2800},
{'scope': u'internal', 'invoiced': 2000, 'initial_boq': 1000},
{'scope': u'internal', 'invoiced': 2000, 'initial_boq': 500},
{'scope': u'external', 'invoiced': 500, 'initial_boq': 1800},
{'scope': u'external', 'invoiced': 150, 'initial_boq': 200},
{'scope': u'both', 'invoiced': 5000, 'initial_boq': 7000}
]
tempJson = {}
finalList = []
for eachScopeJson in list1:
if eachScopeJson['scope'] in tempJson:
tempJson[eachScopeJson['scope']]['invoiced'] = tempJson[eachScopeJson['scope']]['invoiced'] + eachScopeJson['invoiced']
tempJson[eachScopeJson['scope']]['initial_boq'] = tempJson[eachScopeJson['scope']]['initial_boq'] + eachScopeJson['initial_boq']
else:
tempJson[eachScopeJson['scope']] = {}
tempJson[eachScopeJson['scope']]['invoiced'] = 0 + eachScopeJson['invoiced']
tempJson[eachScopeJson['scope']]['initial_boq'] = 0 + eachScopeJson['initial_boq']
for eachKey in tempJson:
finalList.append({'scope':eachKey,'invoiced':tempJson[eachKey]['invoiced'],'initial_boq':tempJson[eachKey]['initial_boq']})
print tempJson
答案 3 :(得分:0)
这里是单线:)
from collections import Counter
from itertools import groupby
key = lambda d: d['scope']
res = [dict(sum((Counter({k:v for k,v in grp.items() if k!='scope'}) for grp in grps), Counter()), scope=scope) for scope,grps in groupby(sorted(lst, key=key), key=key)]
print (res)
[{'invoiced': 5000, 'initial_boq': 7000, 'scope': 'both'}, {'invoiced': 650, 'initial_boq': 2000, 'scope': 'external'}, {'invoiced': 5000, 'initial_boq': 4300, 'scope': 'internal'}]
这是单线的等效代码
key = lambda d: d['scope']
res = []
for scope,grps in groupby(sorted(lst, key=key), key=key):
c = Counter()
for grp in grps:
grp.pop('scope')
c += Counter(grp)
res.append(dict(c, scope=scope))
pprint(res)
答案 4 :(得分:0)
Ciao
比这里已经发布的许多解决方案少得多,但非常清晰
def removeDuplicatedScopesFrom(startingData):
differentScopes = []
for x in startingData:
scope = x["scope"]
if scope not in differentScopes:
differentScopes.append(scope)
return differentScopes
def composeDictionaryElement(scope, invoiced, initial_boq):
return("{'scope': u'" + scope + "', 'invoiced': " + str(invoiced) + ", 'initial_boq': " + str(initial_boq) + "}")
def main():
var = [
{'scope': u'internal', 'invoiced': 1000, 'initial_boq': 2800},
{'scope': u'internal', 'invoiced': 2000, 'initial_boq': 1000},
{'scope': u'internal', 'invoiced': 2000, 'initial_boq': 500},
{'scope': u'external', 'invoiced': 500, 'initial_boq': 1800},
{'scope': u'external', 'invoiced': 150, 'initial_boq': 200},
{'scope': u'both', 'invoiced': 5000, 'initial_boq': 7000}
]
# empty list for the final result
finalList = []
# identifying the different scopes involved
scopes = removeDuplicatedScopesFrom(var)
# scanning the input and joining data from the same scope
for scope in scopes:
# resetting values for each different scope
invoiced = 0;
initial_boq = 0;
# checking all the elements in the list
for y in var:
if y["scope"] == scope:
invoiced = invoiced + y["invoiced"]
initial_boq = initial_boq + y["initial_boq"]
# when list is over we ask to compose the related dictionary element
finalDictionaryElement = composeDictionaryElement(scope, invoiced, initial_boq)
# adding it to the final list
finalList.append(finalDictionaryElement)
# results out without surrounding quotes
print("[%s]" % (', '.join(finalList)))
if __name__== "__main__":
main()
输出
[{'scope': u'internal', 'invoiced': 5000, 'initial_boq': 4300}, {'scope': u'external', 'invoiced': 650, 'initial_boq': 2000}, {'scope': u'both', 'invoiced': 5000, 'initial_boq': 7000}]
希望也有帮助
今天过得好,
安东尼诺