你会在python中使用什么来实现`n到n`的关系?

时间:2011-04-13 17:21:35

标签: data-structures dictionary python

fiddling围绕词典后,我得出结论,我需要一个允许n to n查找的数据结构。一个例子是:几个学生可以访问一门课程,每个学生可以访问几门课程。

实现这一目标的最佳方式是什么?它不会超过500名学生和100门课程,留下这个例子。所以我想避免使用真正的数据库软件。

谢谢!

4 个答案:

答案 0 :(得分:1)

由于您的工作集很小,我认为将学生ID存储为Course类中的列表并不是一个问题。在课堂上找到学生就像做

一样简单
course.studentIDs

要查找学生所在的课程,只需遍历课程并找到ID:

studentIDToGet = "johnsmith001"
studentsCourses = list()
for course in courses:
    if studentIDToGet in course.studentIDs:
        studentsCourses.append(course.id)

还有其他方法可以做到。你可以有一个映射到courseIDs或两个字典的studentID字典 - 一个映射的studentIDs:courseIDs和另一个courseIDs:studentIDs - 更新后,互相更新。

我写出代码的实现可能是最慢的,这就是为什么我提到你的工作集足够小以至于它不会成为问题。我提到的其他实现但没有显示代码,需要更多的代码才能使它们工作,这是不值得的。

答案 1 :(得分:1)

这完全取决于您希望结构能够快速执行的操作。

如果您希望能够快速查找与课程和学生相关的属性,例如学生在特定课程学习上花了多少小时,或者学生在课程中的成绩是多少已完成它,如果他已经完成它等等,你可能需要一个包含 n * m 元素的向量,其中 n 是学生人数和 m 是课程数量。

另一方面,如果学生所选课程的平均数量远少于课程总数(可能是针对实际情况),并且您希望能够快速查找所有课程学生已经学过的课程,您可能想要使用由n个列表组成的数组,链接列表,可调整大小的向量或类似 - 取决于您是否希望能够使用列表;也许这是为了快速删除列表中间的元素,或者快速访问随机位置的元素。如果你们都希望能够快速删除列表中间的元素并快速随机访问列表元素,那么可能某种树形结构最适合你。

大多数树数据结构以对数时间执行树中元素数量的所有基本操作。请注意,某些树数据结构在这些运算符上具有与树中元素数量成线性关系的摊销时间,即使随机构造的树的平均时间是对数的。发生这种情况的一个典型示例是,如果您使用二叉搜索树并使用越来越大的元素构建它。不要那样做;在这种情况下使用它们构建树之前对元素进行加扰,或者使用分而治之的方法将列表拆分为两部分和一个pivot元素,并使用pivot元素创建树根,然后递归创建树从列表的左侧部分和列表的右侧部分,这些也使用分而治之的方法,并将它们分别作为左子项和右子项附加到根。

对不起,我不知道python,所以我不知道哪些数据结构是语言的一部分,你必须自己创建。

答案 2 :(得分:0)

我假设您要为学生和课程编制索引。否则你可以轻松制作一个元组列表来存储所有学生,课程组合:[(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] ... } 

对于一个特定的学生,查找课程现在是学生[s];对于给定的课程c,查找学生是课程[c]。

答案 3 :(得分:0)

对于像你想要的那样简单的东西,你可以用数据成员和方法创建一个简单的类来维护它们并使它们保持一致。对于这个问题,将需要两个字典。一个由学生姓名(或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']