CSV解析书籍

时间:2013-02-21 22:23:06

标签: python django algorithm csv

我正在解决一个项目,我正在解析一个csv文件,该文件将包含教科书的各个部分和子部分,看起来像这样:

Chapter, Section, Lesson  #this line shows how the book will be organized
Ch1Name, Secion1Name, Lesson1Name
Ch1Name, Secion2Name, Lesson1Name
Ch1Name, Secion2Name, Lesson2Name

我正在为每个部分创建Django模型对象,并且每个部分都有一个父属性,它是它所在的父节。我遇到了以这种方式浏览csv文件的方法父分配是正确的。任何有关如何入门的想法都会很棒。

1 个答案:

答案 0 :(得分:1)

首先,希望您已经在使用csv模块而不是尝试手动解析它。

其次,你的问题并不完全清楚,但听起来你正试图在阅读时从数据中建立一个简单的树结构。

那么,这样的事情呢?

with open('book.csv') as book:
    chapters = collections.defaultdict(collections.defaultdict(list))
    book.readline() # to skip the headers
    for chapter_name, section_name, lesson_name in csv.reader(book):
        chapters[chapter_name][section_name].append(lesson_name)

当然,假设你需要一个“关联树”-a dict dict s。更正常的线性树,如list的{​​{1}},或“父指针”形式的隐式树,甚至更简单。

例如,假设你有这样定义的类:

list

你想要每个class Chapter(object): def __init__(self, name): self.name = name class Section(object): def __init__(self, chapter, name): self.chapter = chapter self.name = name class Lesson(object): def __init__(self, section, name): self.section = section self.name = name ,将名称映射到对象。所以:

dict

现在,您可以选择随机课程,并打印其章节和部分:

with open('book.csv') as book:
    chapters, sections, lessons = {}, {}, {}
    book.readline() # to skip the headers
    for chapter_name, section_name, lesson_name in csv.reader(book):
        chapter = chapters.setdefault(chapter_name, Chapter(chapter_name))
        section = sections.setdefault(section_name, Section(chapter, section_name))
        lesson = lessons.setdefault(lesson_name, Lesson(section, lesson_name))

要记住的最后一件事:在此示例中,父引用不会导致任何循环引用,因为父项没有对其子项的引用。但是,如果你需要它呢?

lesson = random.choice(lessons.values())
print('Chapter {}, Section {}: Lesson {}'.format(lesson.section.chapter.name,
                                                 lesson.section.name, lesson.name))

到目前为止,这么好......但是当你完成所有这些对象后会发生什么?它们具有循环引用,这可能导致垃圾收集问题。这不是不可克服的问题,但它确实意味着在大多数实现中不会快速收集对象。例如,在CPython中,一旦最后一个引用超出范围,通常会收集东西 - 但是如果你有循环引用,那么从未发生,所以在循环检测器的下一次传递之前不会收集任何东西。对此的解决方案是使用weakref作为父指针(或子集的class Chapter(object): def __init__(self, name): self.name = name self.sections = {} class Section(object): def __init__(self, chapter, name): self.chapter = chapter self.name = name self.lessons = {} # ... chapter = chapters.setdefault(chapter_name, Chapter(chapter_name)) section = sections.setdefault(section_name, Section(chapter, section_name)) chapters[section_name] = section )。