Py学习  »  Python

在python中处理嵌入在字典列表中的元组列表

tsb • 5 年前 • 1711 次点击  

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

在这一点上,我们还没有讨论导入任何额外的特性(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):

编辑

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

def highest_n_grades(student_list):
  for s in student_list:
    for assignment_name, grade in s['assignments']:
        if int(grade) >= 4:
            print(assignment_name, grade)

highest_n_grades(student_list)

编辑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

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)]}]
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/46317
 
1711 次点击  
文章 [ 2 ]  |  最新文章 5 年前
Nick
Reply   •   1 楼
Nick    6 年前

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

lambda是一个动态定义的小函数。 sorted() 将函数作为其第二个参数。它需要为每个学生调用此函数来生成排序键。sort函数比较两个学生的排序键,以确定在排序中哪个学生先进入。

从lambdas开始,最好记住:

id_key = lambda x: x[0]

相当于:

def id_key(x):
    return x[0]

此外

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]

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

例如:

print('Highest grades dict version...')
grades = highest_n_grades_dict(students_dict, 'assignment_2', 2)
print(grades)
print("...and dict structure easily allows us to get other student details")
names_and_grades = [
    (students_dict[id]['first_name'] + ' ' + students_dict[id]['last_name'], grade)
    for id, grade
    in grades]
print(names_and_grades)
>>> python grades.py
Highest grades dict version...
[(12343, 4), (12342, 3)]
...and dict structure easily allows us to get other student details
[('Carl Cape', 4), ('Boris Bank', 3)]

旁注:如果你经常和元组打交道,你可能会对 named tuples ,因为它们通常使元组相关的代码(包括lambda函数)更易于读、写和理解。看看我最近的回答 this question 举个例子。

vash_the_stampede
Reply   •   2 楼
vash_the_stampede    6 年前

这可以用 lambda sorted 是的。使用时 已排序 具有 兰姆达 我们先出发 key=lambda x: 是的。现在你可以想想了 x 表示列表索引,以便按 assignment_1 我们要走了 x['assignments'] 如果我们的任务是 任务1 我们知道那是 0 索引 assignments 所以在一起 key=lambda x: x['assignments'][0] 是的。现在我们也可以 sort 第二个选择,那将是我们的平局,我们将使用 x[id] 并将与我们的主要排序因子在一个元组中。我们当然应该用 reverse = True 为了得到下降的分数,但是由于我们希望我们的平局是上升的,所以我们可以在 id 使用 -(x['id'])

总的来说,这类情况如下:

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

棘手的部分是为传递的赋值选择合适的赋值索引,因为您可以使用 .split('_')[1] (使用时 .split('_') 'assignment_1' 我们生成一个新列表 ['assignemnt', '1'] 在这种情况下,我们现在可以采取 [1] 索引 .split() 那就是 1 作为 int 减去1得到 0个 这是相应的索引,其余的都是从它们的索引中去掉1。

def highest_n_grades(students, assignment_name, n):
    y = int(assignment_name.split('_')[1]) - 1
    lista = sorted(students, key=lambda x: (x['assignments'][y], 'id'), reverse = True)
    return lista [:n]   

print(highest_n_grades(student_list, 'assignment_1', 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)]}]

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

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

关于使用 已排序

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