2013-02-21 66 views
0

我有一個項目中,我解析一個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文件的方式,以使父分配正確。如何開始的任何想法都會很棒。

+0

希望CSV中的數據沒有空格,或者讓事情變得有趣。無論如何,[請看看Python中的csv模塊。](http://docs.python.org/2/library/csv.html) – Makoto 2013-02-21 22:26:28

回答

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 dictdict S的。更正常的線性樹,如listlist s,或者以「父指針」形式的隱式樹,甚至更簡單。

例如,假設你有一個像這樣定義類:

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集合)。

+0

謝謝。我實際上正在使用csv模塊,但感謝您的建議。我認爲你已經接近我的想法,但問題在於:例如,從上面的csv示例中,我需要Chapter1中的Section1和Secion2指向同一個Chapter1節對象。我希望這是有道理的。 – taman 2013-02-21 23:01:29

+0

好的,你想建立某種'Section'對象?讓我編輯答案。 – abarnert 2013-02-21 23:43:31

+0

謝謝!我認爲這會幫助我解決問題! – taman 2013-02-22 01:13:19