0

教科書のセクションとサブセクションを含むcsvファイルを解析しているプロジェクトで問題が発生しました。これは次のようになります。

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

セクションごとにDjangoモデルオブジェクトを作成していますが、各セクションには、それが存在する親セクションである親属性があります。親がcsvファイルを処理する方法を思い付くのに問題があります。割り当ては正しいです。始める方法についてのアイデアは素晴らしいでしょう。

4

1 に答える 1

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)

もちろん、これは「連想ツリー」が必要であることを前提としていdictますdictlistsのような、より通常の線形ツリー、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))

最後に覚えておくべきことは、この例では、親には子への参照がないため、親の参照によって循環参照が発生することはありません。しかし、それが必要な場合はどうなりますか?

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

これまでのところ、とても良いです…しかし、これらすべてのオブジェクトを使い終わったらどうなりますか?それらには循環参照があり、ガベージコレクションの問題を引き起こす可能性があります。克服できない問題ではありませんが、ほとんどの実装でオブジェクトがすぐに収集されないことを意味します。たとえば、CPythonでは、通常、最後の参照がスコープ外になるとすぐに収集されますが、循環参照がある場合は発生しないため、サイクル検出器の次のパスまで何も収集されません。これに対する解決策はweakref、親ポインター(またはweakref子へのsのコレクション)にaを使用することです。

于 2013-02-21T22:28:46.313 に答える