在python中使用嵌入在字典列表中的元组列表

2024-04-29 04:02:28 发布

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

我在一个初级的编码班,我似乎不能把我所教的基础知识变成一个有着如此复杂的列表的工作程序。我应该使用什么函数来执行此操作?在

在这一点上,我们还没有讨论导入任何额外的特性(numpy等等),我知道人们经常使用lambda(尽管我不太明白它的作用),但是这门课还没有介绍过。在

#This is an example of the structure of a student dictionary
#They have an id number
#They have a first name, last name and a list of assignments
#Assignments are tuples of an assignment name and grade
#The grade is a 4 point scale from 0 to 4
'''
student_list = [{'id': 12341, 'first_name': 'Alice', 'last_name': 'Anderson',
     'assignments': [('assignment_1', 0), ('assignment_2', 2), ('assignment_3', 4)]},

 {'id': 12342, 'first_name': 'Boris', 'last_name': 'Bank',
   'assignments': [('assignment_1', 1), ('assignment_2', 3), ('assignment_3', 0)]},

 {'id': 12343, 'first_name': 'Carl', 'last_name': 'Cape',
   'assignments': [('assignment_1', 2), ('assignment_2', 4), ('assignment_3', 1)]},

 {'id': 12344, 'first_name': 'Didi', 'last_name': 'Dawson',
   'assignments': [('assignment_1', 3), ('assignment_2', 0), ('assignment_3', 2)]},

 {'id': 12345, 'first_name': 'Ed', 'last_name': 'Enders',
   'assignments': [('assignment_1', 4), ('assignment_2', 1), ('assignment_3', 3)]}]

#This function should return a list of the n student dictionaries with the
#highest grades on the assignment passed in as assignment name
#If there is a tie then it is broken by returning the student(s) with the
#lowest id number(s)
def highest_n_grades(students, assignment_name, n):

编辑

对不起,我不想得到答案。我明白了。我觉得我写了很多东西,删除了很多,这就是我的问题。我连开始都有困难。在

我希望在正确的方向上找到一个正确的方向,比如什么命令可以获得最高的分数等等。到目前为止,我真正拥有的是:

^{pr2}$

但我知道这并不能让我真正开始。它没有三个输入,也没有寻找最大值,它在寻找手动输入的值4,它甚至没有接近于将at与学生姓名联系起来,也没有形成另一个列表。在

编辑2

我也试过了,结果出了一个错误,我试着对字典而不是列表进行排序。在

def highest_n_grades(student_list, assignment_name):
  for s in student_list:
    for assignment_name in s['assignments'][1]:
      s['assignments'][1] = assignment_name
      s.sort(key=assignment_name)
    print(student_list)

highest_n_grades(student_list, assignment_name='assignment_1' )

编辑3

好吧,我也许有点进展了?在

newlist2 = sorted(newlist, key=lambda k: k['assignments'][0], reverse = True)
newlist3 = sorted(newlist, key=lambda k: k['assignments'][1], reverse = True)
newlist4 = sorted(newlist, key=lambda k: k['assignments'][2], reverse = True)

这些似乎是按任务排序的。我不明白lambda在做什么,但我至少可以生成一个最高分的列表。我觉得这只是小步走。在

编辑4

这是我创建的一个函数。它似乎得到了我想要的,它输出最高的3个学生,但它打印了5次?我知道这不是很灵活,但这只是个开始。在

def highest_n_grades(student_list,  n):
  for s in student_list:
    newlist = sorted(student_list, key=lambda k: k['assignments'][0], reverse=True)
    print(newlist[:n])

highest_n_grades(student_list, 3)

输出:

[{'id': 12345, 'first_name': 'Ed', 'last_name': 'Enders', 'assignments': [('assignment_1', 4), ('assignment_2', 1), ('assignment_3', 3)]}, {'id': 12344, 'first_name': 'Didi', 'last_name': 'Dawson', 'assignments': [('assignment_1', 3), ('assignment_2', 0), ('assignment_3', 2)]}, {'id': 12343, 'first_name': 'Carl', 'last_name': 'Cape', 'assignments': [('assignment_1', 2), ('assignment_2', 4), ('assignment_3', 1)]}]
[{'id': 12345, 'first_name': 'Ed', 'last_name': 'Enders', 'assignments': [('assignment_1', 4), ('assignment_2', 1), ('assignment_3', 3)]}, {'id': 12344, 'first_name': 'Didi', 'last_name': 'Dawson', 'assignments': [('assignment_1', 3), ('assignment_2', 0), ('assignment_3', 2)]}, {'id': 12343, 'first_name': 'Carl', 'last_name': 'Cape', 'assignments': [('assignment_1', 2), ('assignment_2', 4), ('assignment_3', 1)]}]
[{'id': 12345, 'first_name': 'Ed', 'last_name': 'Enders', 'assignments': [('assignment_1', 4), ('assignment_2', 1), ('assignment_3', 3)]}, {'id': 12344, 'first_name': 'Didi', 'last_name': 'Dawson', 'assignments': [('assignment_1', 3), ('assignment_2', 0), ('assignment_3', 2)]}, {'id': 12343, 'first_name': 'Carl', 'last_name': 'Cape', 'assignments': [('assignment_1', 2), ('assignment_2', 4), ('assignment_3', 1)]}]
[{'id': 12345, 'first_name': 'Ed', 'last_name': 'Enders', 'assignments': [('assignment_1', 4), ('assignment_2', 1), ('assignment_3', 3)]}, {'id': 12344, 'first_name': 'Didi', 'last_name': 'Dawson', 'assignments': [('assignment_1', 3), ('assignment_2', 0), ('assignment_3', 2)]}, {'id': 12343, 'first_name': 'Carl', 'last_name': 'Cape', 'assignments': [('assignment_1', 2), ('assignment_2', 4), ('assignment_3', 1)]}]
[{'id': 12345, 'first_name': 'Ed', 'last_name': 'Enders', 'assignments': [('assignment_1', 4), ('assignment_2', 1), ('assignment_3', 3)]}, {'id': 12344, 'first_name': 'Didi', 'last_name': 'Dawson', 'assignments': [('assignment_1', 3), ('assignment_2', 0), ('assignment_3', 2)]}, {'id': 12343, 'first_name': 'Carl', 'last_name': 'Cape', 'assignments': [('assignment_1', 2), ('assignment_2', 4), ('assignment_3', 1)]}]

Tags: thelambdanameidstudentlistfirstlast
2条回答

对于初学者来说,这是一项困难的作业。困难在于lambda、多键排序、列表、列表切片和元组、字典,甚至是有序与无序的数据类型。我用Python编程已经有10年了,但我并不觉得它很简单。在

lambda是一个很小的函数,你可以随时定义它。sorted()接受一个函数作为其第二个参数。它需要为每个学生调用这个函数来生成一个排序键。sort函数比较两个学生的排序键,以确定排序中哪个学生先排序。在

从lambdas开始,最好记住:

id_key = lambda x: x[0]

相当于:

^{pr2}$

此外

sorted(students, key=lambda x: x[0])

相当于:

sorted(student, key=id_key)

为了对多个值进行排序,我将查看stable sorts and their properties。稳定的排序算法非常适合对多个值进行排序。大多数Python排序函数都是“稳定的”。在

以下是使用当前结构的解决方案:

def sort_by_grade_then_id(grades):
    # sort (id, grade) tuples high grades, low ids first
    sorted_by_id = sorted(grades, key=lambda student: student[0])
    sorted_by_id_and_assignment_grade = sorted(sorted_by_id,
        key=lambda student: student[1], reverse=True)
    return sorted_by_id_and_assignment_grade


def highest_n_grades(students, assignment_name, n):
grades = []
for student in students:
    for assignment, grade in student['assignments']:
        if assignment_name == assignment:
            grades.append((student['id'], grade))
return sort_by_grade_then_id(grades)[:n]    

>>> print(highest_n_grades(student_list, 'assignment_2', 2))
[(12343, 4), (12342, 3)]

但是如果你现在想要的是学生的名字而不是他/她的身份证,你必须再做一次序列搜索才能得到。在

作为一种不同的方法,下面将原始的基于列表的学生数据库复制到基于词典的数据库中。在

from copy import copy

students_dict = {student['id']: student for student in copy(student_list)}
for student in students_dict.values():
    student['assignments'] = dict(student['assignments'])

列出最高分将变成:

def highest_n_grades_dict(students, assignment_name, n):
    grades = [
        (id, student['assignments'][assignment_name])
        for id, student
        in students.items()
    ]
    return sort_by_grade_then_id(grades)[:n]

对少数学生来说并不重要,但是如果你有很多学生和许多作业,这个新版本会更快。你现在也可以使用学生数据库来查找资料,而不必搜索和匹配。在

例如:

^{8}$

旁注:如果您经常处理元组,您可能会对named tuples感兴趣,因为它们通常使元组相关的代码(包括lambda函数)更易于读、写和理解。请看我最近对this question的回答,以获取一个示例。在

这可以使用lambdasorted来完成。当将sortedlambda一起使用时,我们先设置key=lambda x:。现在您可以考虑代表一个列表索引的x,所以要按assignment_1排序,我们要去x['assignments']这将带我们到赋值,下一步,如果我们的赋值是assignment_1,我们知道这是assignments的{}索引,所以它一起就是key=lambda x: x['assignments'][0]。现在我们还可以sort一个二级选项,这将是我们的“决胜符”,我们将使用x[id],并将与我们的主要排序因子在一个元组中。当然,我们应该使用reverse = True来得到递减的分数,但是由于我们希望我们的平局是按升序排列的,所以我们可以使用-(x['id'])来抵消id上的相反值

总的来说,这类人看起来是这样的:

lista = sorted(students, key=lambda x: (x['assignments'][0], -(x['id'])), reverse = True)

棘手的是为传递的赋值选择合适的赋值索引,为此,您可以使用.split('_')[1](当在'assignment_1'上使用.split('_')时,我们生成了一个新的列表['assignemnt', '1']。在这种情况下,我们现在可以将.split()[1]作为int并减去1得到0,这是相应的索引,而对于其余的,则是它们的索引都是1。在

^{pr2}$

使用伪分数演示平局案例:

print(highest_n_grades(student_list, 'assignment_1', 3))
# [{'id': 12344, 'first_name': 'Didi', 'last_name': 'Dawson', 'assignments': [('assignment_1', 4), ('assignment_2', 0), ('assignment_3', 2)]}, {'id': 12345, 'first_name': 'Ed', 'last_name': 'Enders', 'assignments': [('assignment_1', 4), ('assignment_2', 1), ('assignment_3', 3)]}, {'id': 12342, 'first_name': 'Boris', 'last_name': 'Bank', 'assignments': [('assignment_1', 2), ('assignment_2', 3), ('assignment_3', 0)]}]

进一步阅读

.split()

https://docs.python.org/3/library/stdtypes.html

关于使用sorted

https://docs.python.org/3/library/functions.htmlhttps://wiki.python.org/moin/HowTo/Sorting

相关问题 更多 >