在字典结构中聚合数据以返回3个元组的平均值列表

2024-10-05 15:30:50 发布

您现在位置:Python中文网/ 问答频道 /正文

stats1函数接受一个dict参数并返回3元组列表,其中包含一个str(提供者)、一个int(他/她提供的服务数量)和一个float(平均专业水平)。结果必须按提供程序的名称排序。调用stats1(db1)返回:

[('Al', 2, 1.5), ('Bob', 2, 2.0), ('Carol', 3, 1.3333333333333333)]

请注意,Al提供2项服务,其平均专业水平为1.5(2级遛狗,1级绘画)。你知道吗

db1 = {
    ('Al', 'dog-walking'): 2,
    ('Al', 'painting'): 1,
    ('Bob', 'dog-walking'): 1,
    ('Bob', 'knife-sharpening'): 3,
    ('Carol', 'cleanup'): 1,
    ('Carol', 'dog-walking'): 2,
    ('Carol', 'painting'): 1
}

我没有添加正确的值到我的解决方案,我有困难排序它。你知道吗

到目前为止我所拥有的:

def stats(db1):
    d=defaultdict(lambda:[0,0])
    z=1
    for nametuple, expertlevel in db1.items():
        d[nametuple[0]][0]+=1
        if  d[nametuple[0]][1]==0:
            d[nametuple[0]][1]+=expertlevel
        else:
            d[nametuple[0]][1]+=expertlevel/z
            z+=1
    #return d
    return sorted(d.items(),key=lambda x: (-[x][0],x[1],d))
print(stats(db1))

如何修复代码?你知道吗


Tags: lambda专业排序stats水平bobaldog
3条回答

您还可以使用列表理解:

def avg(lst):
    return sum(lst)/len(lst)

print(sorted([(name,[key[0] for key in db1.keys()].count(name), avg([val for key,val in db1.items() if key[0]==name])) for name in set([key[0] for key in db1.keys()])],key=lambda x: x[0]))

>>>[('Al', 2, 1.5), ('Bob', 2, 2.0), ('Carol', 3, 1.3333333333333333)]

平均值的算法不正确,需要执行以下操作:

def stats(db1):
    d=defaultdict(lambda:[0,0])
    for nametuple, expertlevel in db1.items():
        d[nametuple[0]][0]+=1
        d[nametuple[0]][1] = (d[nametuple[0]][1]*(d[nametuple[0]][0]-1)+expertlevel)/d[nametuple[0]][0]

    #return d
    return d.items()
print(stats(db1))

输出:

dict_items([('Al', [2, 1.5]), ('Bob', [2, 2.0]), ('Carol', [3, 1.3333333333333333])])

但更明确的答案是(根据ggorlen's comment编辑):

from itertools import groupby

lst = []
for k,g in groupby(sorted(db1.items()), lambda x:x[0][0]):
    provider = k
    args = list(g)
    services = len(args)
    expertise = sum(elem[1] for elem in args)/services
    lst.append((provider, services, expertise))

print(lst)

输出:

[('Al', 2, 1.5), ('Bob', 2, 2.0), ('Carol', 3, 1.3333333333333333)]

你说得对,我喜欢defaultdict方法。如果将平均步骤与聚合步骤分离,您可能会发现该逻辑更易于管理。你知道吗

中间dict应该包含每个映射到服务级别列表的提供者名称键。循环dict中的每个人,并取他们服务的平均值来构建结果元组。所提供的服务的数量隐含着列表的长度。你知道吗

对元组的排序有很好的定义(默认情况下,它们将在第一个元素上排序),因此不需要指定key。你知道吗

>>> from collections import defaultdict
>>> stats = defaultdict(list)
>>> for k, v in db1.items():
...     stats[k[0]].append(v)
...
>>> sorted((k, len(v), sum(v) / len(v)) for k, v in stats.items())
[('Al', 2, 1.5), ('Bob', 2, 2.0), ('Carol', 3, 1.3333333333333333)]

相关问题 更多 >