您将如何在python中使用“ n对n”关系?

| 在摆弄字典之后,我得出的结论是,我需要一个允许我进行“ 0”查找的数据结构。一个示例是:几名学生可以访问一门课程,每位学生可以访问几门课程。 实现这一目标的最Python方式是什么?保持这个例子不会超过500名学生和100门课程。所以我想避免使用真正的数据库软件。 谢谢!     
已邀请:
由于您的工作量很小,我认为仅将学生ID作为列表存储在Course类中就不会有问题。在班上找学生就像在做一样简单
course.studentIDs
要查找学生所在的课程,只需遍历课程并找到ID:
studentIDToGet = \"johnsmith001\"
studentsCourses = list()
for course in courses:
    if studentIDToGet in course.studentIDs:
        studentsCourses.append(course.id)
您还有其他方法可以做到。您可能有一个映射到课程ID的学生ID字典,或者两个字典-一个映射的学生ID:课程ID和另一个课程ID:学生ID-更新后,彼此更新。 我写出代码的实现可能是最慢的,这就是为什么我提到您的工作集足够小而不会造成问题的原因。我提到但没有显示代码的其他方法将需要更多代码才能使它们工作,这是不值得的。     
这完全取决于您希望结构能够快速执行的操作。 如果您希望能够快速查找与课程和学生相关的属性,例如,学生在特定课程的学习上花费了几个小时,或者如果学生完成了该课程,则获得该课程的等级,如果他完成了此等操作,则可能需要包含n * m个元素的向量,其中n是学生数,m是课程数。 另一方面,如果学生平均修读的课程数量少于课程总数(这可能是实际情况),并且您希望能够快速查找学生的所有课程已经,您可能想使用由n个列表组成的数组,这些列表可以是链表,可调整大小的向量或类似的列表,具体取决于您是否希望使用列表;也许是要快速删除列表中间的元素,或者快速访问随机位置的元素。如果您都希望能够快速删除列表中间的元素,并且可以快速随机访问列表元素,那么某种树形结构可能最适合您。 大多数树数据结构会以对数时间执行所有基本操作,时间与树中元素的数量有关。请注意,即使随机构造的树的平均时间是对数的,某些树数据结构在这些运算符上的摊销时间也与树中元素的数量成线性关系。发生这种情况的一个典型示例是,如果您使用二叉搜索树并使用越来越大的元素来构建它。不要那样做;在这种情况下,您需要先对元素进行打乱,然后再使用分治法将列表分为两部分和一个数据透视元素,然后使用数据透视元素创建树根,然后递归创建树从列表的左部分和列表的右部分开始,它们还使用分而治之方法,并将它们分别作为左孩子和右孩子附加到根。 对不起,我不了解python,所以我不知道语言中包含哪些数据结构以及您必须创建自己的数据结构。     
我假设您想同时索引学生和课程。否则,您可以轻松地创建一个元组列表来存储所有Student,Course组合:[(St1,Crs1),(St1,Crs2)..(St2,Crs1)...(Sti,Crsi)...],然后每次都需要进行线性查找。对于多达500名学生来说,这也不错。 但是,如果您想以任何一种方式快速查找,则没有内置的数据结构。您可以简单地使用两个字典:
courses = { crs1: [ st1, st2, st3 ], crs2: [ st_i, st_j, st_k] ... } 
students = { st1: [ crs1, crs2, crs3 ], st2: [ crs_i, crs_j, crs_k] ... } 
对于给定的学生,查找课程即为学生;对于给定的课程c,查找学生就是课程[c]。     
对于像您想要做的事情一样简单的事情,您可以创建一个简单的类,其中包含数据成员和方法以维护它们并使它们彼此保持一致。对于这个问题,将需要两个字典。一个用学生姓名(或ID)作为关键字,可以跟踪每个课程的学习情况,另一个可以跟踪每个班级的学生。 可以使用\'collections \'模块中的
defaultdicts
代替普通的
dicts
,以便使事情更方便。这是我的意思:
from collections import defaultdict

class Enrollment(object):
    def __init__(self):
        self.students = defaultdict(set)
        self.courses = defaultdict(set)

    def clear(self):
        self.students.clear()
        self.courses.clear()

    def enroll(self, student, course):
        if student not in self.courses[course]:
            self.students[student].add(course)
            self.courses[course].add(student)

    def drop(self, course, student):
        if student in self.courses[course]:
            self.students[student].remove(course)
            self.courses[course].remove(student)
        # remove student if they are not taking any other courses
        if len(self.students[student]) == 0:
            del self.students[student]

    def display_course_enrollments(self):
        print \"Class Enrollments:\"
        for course in self.courses:
            print \'  course:\', course,
            print \' \', [student for student in self.courses[course]]

    def display_student_enrollments(self):
        print \"Student Enrollments:\"
        for student in self.students:
            print \'  student\', student,
            print \' \', [course for course in self.students[student]]

if __name__==\'__main__\':

    school = Enrollment()

    school.enroll(\'john smith\', \'biology 101\')
    school.enroll(\'mary brown\', \'biology 101\')
    school.enroll(\'bob jones\', \'calculus 202\')

    school.display_course_enrollments()
    print
    school.display_student_enrollments()

    school.drop(\'biology 101\', \'mary brown\')
    print
    print \'After mary brown drops biology 101:\'
    print
    school.display_course_enrollments()
    print
    school.display_student_enrollments()
运行时会产生以下输出:
Class Enrollments:
  course: calculus 202   [\'bob jones\']
  course: biology 101   [\'mary brown\', \'john smith\']

Student Enrollments:
  student bob jones   [\'calculus 202\']
  student mary brown   [\'biology 101\']
  student john smith   [\'biology 101\']

After mary brown drops biology 101:

Class Enrollments:
  course: calculus 202   [\'bob jones\']
  course: biology 101   [\'john smith\']

Student Enrollments:
  student bob jones   [\'calculus 202\']
  student john smith   [\'biology 101\']
    

要回复问题请先登录注册