【每日一题1029】最佳成绩

:woman_mage:火焰杯测试大赛刚刚落下帷幕,学院的教员们就开始着手统计魔法师们的比赛成绩。但是发现一个奇怪的事情,有些答卷出现了重复,可能是淘气的魔法师使用了镜像法术尝试交了多份试题。请编写一个函数,接收一个包含成绩统计信息字典对象的列表info,以名字name为依据去重,并返回每个人最佳的分数信息。

题目难度:简单
题目来源:蚊子(故事情节纯属虚构,如有雷同纯属巧合)

info = [{"name": "AD", "group": "full stack", "score": 99},
       {"name": "蚊子", "group": "backend", "score": 93},
       {"name": "北北", "group": "frontend", "score": 90},
       {"name": "AD", "group": "full stack", "score": 88},
       {"name": "蚊子", "group": "backend", "score": 101}]

def the_best(info) -> dict:
    pass

assert the_best(info) == [{"name": "AD", "group": "full stack", "score": 99},
        {"name": "蚊子", "group": "backend", "score": 101},
       {"name": "北北", "group": "frontend", "score": 90}]
def the_best(info):
    temp_dict=[]
    name_list=[]
    for i in info:
        if i["name"] not in name_list:
            name_list.append(i["name"])
            temp_dict.append(i)
        else:
            for j in temp_dict:
                if i["name"]==j["name"] and i["score"]>j["score"]:
                    j["score"]=i["score"]
    return temp_dict
info = [{"name": "AD", "group": "full stack", "score": 99},
        {"name": "蚊子", "group": "backend", "score": 93},
        {"name": "北北", "group": "frontend", "score": 90},
        {"name": "AD", "group": "full stack", "score": 88},
        {"name": "蚊子", "group": "backend", "score": 101}]


def the_best(info) -> list:
    best_list = []
    for d1 in info:
        if len(best_list) > 0:
            for d2 in best_list:
                if d1['name'] == d2['name']:
                    if d1['score'] > d2['score']:
                        best_list[best_list.index(d2)] = d1
                    break
            else:
                best_list.append(d1)
        else:
            best_list.append(d1)
    return best_list


assert the_best(info) == [{"name": "AD", "group": "full stack", "score": 99},
                          {"name": "蚊子", "group": "backend", "score": 101},
                          {"name": "北北", "group": "frontend", "score": 90}]
def the_best(info) -> list:
    result = []
    names = []
    for i in info:
        if i["name"] not in names:
            names.append(i["name"])
            result.append(i)
        else:
            index = names.index(i["name"])
            if result[index]["score"] < i["score"]:
                result[index] = i
    return result


assert the_best(info) == [{"name": "AD", "group": "full stack", "score": 99},
                          {"name": "蚊子", "group": "backend", "score": 101},
                          {"name": "北北", "group": "frontend", "score": 90}]

def the_best(info) -> dict:
    list1 = []
    name_list = []
    for i in info:
        if i['name'] not in name_list:
            list1.append(i)
            name_list.append(i['name'])
        else:
            for j in list1:
                if i['name'] == j['name'] and i['score'] > j['score']:
                    j['score'] = i['score']
    return list1


assert the_best(info) == [{"name": "AD", "group": "full stack", "score": 99},
                          {"name": "蚊子", "group": "backend", "score": 101},
                          {"name": "北北", "group": "frontend", "score": 90}]

Python参考题解(简单)

info = [{"name": "AD", "group": "full stack", "score": 99},
       {"name": "蚊子", "group": "backend", "score": 93},
       {"name": "北北", "group": "frontend", "score": 90},
       {"name": "AD", "group": "full stack", "score": 88},
       {"name": "蚊子", "group": "backend", "score": 101}]


def the_best(info) -> dict:
    
    names = []
    for item in info:
        name = item['name']
        if name not in names:
            names.append(name)
        continue
    
    grouped = []
    for name in names:
        li = [x for x in info if x['name'] == name]
        grouped.append(li)

    
    best_li = []
    for item in grouped:
        maxs = max(item, key=lambda x:x['score'])
        best_li.append(maxs)
    return best_li


assert the_best(info) == [{"name": "AD", "group": "full stack", "score": 99},
        {"name": "蚊子", "group": "backend", "score": 101},
       {"name": "北北", "group": "frontend", "score": 90}]

思路:使用for循环,三步走。第一步,获取所有唯一的姓名列表;第二步,根据姓名分别收集各自的信息,相当于分组;第三步,针对每个人保留其最佳成绩信息。

代码解析:

  • 第一段
    names = []
    for item in info:
        name = item['name']
        if name not in names:
            names.append(name)
        continue

上面这一段是使用循环,求出去重后,实际选手的名字,得到结果:[‘AD’, ‘蚊子’, ‘北北’]。之所以没有直接用集合set是因为断言中约定了排列顺序。


  • 第二段
    grouped = []
    for name in names:
        li = [x for x in info if x['name'] == name]
        grouped.append(li)

上面这一段,遍历姓名列表,分别将每个人的成绩信息进行分组,以便后面使用内置函数max()来求大最值。
grouped结果是:

[
  [
    {'name': 'AD', 'group': 'full stack', 'score': 99}, 
    {'name': 'AD', 'group': 'full stack', 'score': 88}
  ], 
  [
    {'name': '蚊子', 'group': 'backend', 'score': 93}, 
    {'name': '蚊子', 'group': 'backend', 'score': 101}
  ], 
  [{'name': '北北', 'group': 'frontend', 'score': 90}]
]

  • 第三段

下面这段,对分组的数据,按照分数作为规则,保留最大的那一项。

    best_li = []
    for item in grouped:
        maxs = max(item, key=lambda x:x['score'])
        best_li.append(maxs)
    return best_li

Python参考题解:高阶函数itertools.groupby()

info = [{"name": "AD", "group": "full stack", "score": 99},
       {"name": "蚊子", "group": "backend", "score": 93},
       {"name": "北北", "group": "frontend", "score": 90},
       {"name": "AD", "group": "full stack", "score": 88},
       {"name": "蚊子", "group": "backend", "score": 101}]

from itertools import groupby

def the_best(info) -> dict:

    # 指定排序的规则(被自己的断言给钳制了😭)
    rule = ['AD', '蚊子', '北北']
    info.sort(key=lambda x:rule.index(x['name']))

    # 使用groupby生成器函数进行分组
    data = groupby(info, key=lambda x:x['name'])

    # 遍历分组数据,利用推导式,为每位选手保留满足条件的最大项
    return [max(group, key=lambda x:x['score']) for k, group in data]
info = [{"name": "AD", "group": "full stack", "score": 99},
        {"name": "蚊子", "group": "backend", "score": 93},
        {"name": "北北", "group": "frontend", "score": 90},
        {"name": "AD", "group": "full stack", "score": 88},
        {"name": "蚊子", "group": "backend", "score": 101}]


def the_best(info) -> dict:
    # 存储不同的name
    names = []
    # 结果
    result = []
    for data in info:
        # 遍历info列表中的字典元素,如果name的值不在names和result列表中,则添加
        # 如果name的值已经在names列表中,则表明是重复数据,这时先获取name值在names列表中的索引
        # 再判断result中相同索引的name的score值是否比重复出现的name的socre小
        # 如果小,则用重复出现的name的整个data数据替换result中原先的数据
        if data['name'] not in names:
            names.append(data['name'])
            result.append(data)
        else:
            i = names.index(data['name'])
            if result[i]['score'] < data['score']:
                result[i] = data
    return result


assert the_best(info) == [{"name": "AD", "group": "full stack", "score": 99},
                          {"name": "蚊子", "group": "backend", "score": 101},
                          {"name": "北北", "group": "frontend", "score": 90}]