2017-10-08 69 views
0

我目前在採取一些學校的計算機科學課程,並已經來到了一個死衚衕,並需要一點點幫助的屬性列表。就像標題所說的那樣,我需要從一個文件中創建一個Class對象列表,其中包含一個沒有添加到列表中的副本的對象,我可以用python set()成功完成此操作,但顯然這是不允許的任務,我嘗試了各種其他方法,但似乎無法使用一套工作。我相信這個任務的重點是比較Python中的數據結構,並使用最慢的方法,因爲它也必須定時。我的代碼將使用set()將提供。創建類的對象從一個文件中,沒有重複的對象

import time 

class Students: 
    def __init__(self, LName, FName, ssn, email, age): 
     self.LName = LName 
     self.FName = FName 
     self.ssn = ssn 
     self.email = email 
     self.age = age 

    def getssn(self): 
     return self.ssn 

def main(): 
    t1 = time.time() 
    f = open('InsertNames.txt', 'r') 
    studentlist = [] 
    seen = set() 
    for line in f: 
     parsed = line.split(' ') 
     parsed = [i.strip() for i in parsed] 
     if parsed[2] not in seen: 
      studentlist.append(Students(parsed[0], parsed[1], parsed[2], parsed[3], parsed[4])) 
      seen.add(parsed[2]) 
     else: 
      print(parsed[2], 'already in list, not added') 
    f.close() 
    print('final list length: ', len(studentlist)) 
    t2 = time.time() 
    print('time = ', t2-t1) 
main() 

需要注意的是,唯一需要檢查的重複項是那些.ssn屬性,並且不應將重複項添加到列表中。有沒有辦法在添加之前通過該特定屬性檢查列表中已有的內容?

編輯:忘記提到只有1允許在內存中的列表。

+0

考慮寫'學生(*解析)'有隱含檢查字段數的優勢。 (並命名爲'Student',因爲它只是一個。) –

+0

我喜歡'(* parsed)'技巧!感謝那! – deadsightsx

回答

0

你可以寫

if not any(s.ssn==parsed[2] for s in studentlist): 

不承諾這個比較作爲==意義。在這個級別的工作中,您可能需要寫出循環並自己設置一個標誌,而不是使用生成器表達式。

+0

啊,你的回答讓我想起了我遺漏的一個細節,在內存中只允許有1個列表。 – deadsightsx

+0

@deadsightsx:希望'split()'產生的列表不計數! –

+0

我不認爲這樣做,否則教授應該提到,我第一次向他展示代碼,謝謝你的答案,但它似乎做了什麼意圖,因爲它比'set()'更痛苦地慢: ) – deadsightsx

0

由於您已經花時間編寫代表學生的課程,並且由於ssn是實例的唯一標識符,因此請考慮爲該課程編寫__eq__方法。

def __eq__(self, other): 
    return self.ssn == other.ssn 

這會讓你的生活更輕鬆,當你想比較兩個學生,並在你的情況做一個list(特別不是set)的學生。

那麼你的代碼看起來是這樣的:

with open('InsertNames.txt') as f: 
    for line in f: 
     student = Student(*line.strip().split()) 
     if student not in student_list: 
      student_list.append(student) 

說明

  1. 打開與with聲明文件,使你的代碼更乾淨, 給它處理錯誤和做的能力清理正確。而 因爲'r'open的默認值,所以不需要在那裏。
  2. 你應該strip的線分割只是爲了處理一些 邊緣情況之前,但這不是強制性的。
  3. split的默認參數爲' '所以這又是沒有必要的。 只是澄清這個項目的含義是沒有參數使split使用空格。這並不意味着單個空格字符是默認字符。
  4. 將其添加到列表之前創建學生聽起來像這樣簡單的使用太 的開銷,但由於只有一個叫 __init__方法是不那麼糟糕。這個 的好處在於,它使得代碼在not in語句中更具可讀性。
  5. in聲明(當然還有not in)會檢查對象是否在該對象的__eq__方法中。 由於您使用了該方法,因此可以檢查in語句 中的Student類實例。

只有當學生不在列表中時,纔會被添加。

最後一件事情是,除了您創建的splitstudent_list的返回值之外,此處沒有創建列表。

+0

'str.split'的默認值是[複雜](https://docs.python.org/3/library/stdtypes.html#text-sequence-type-str)。 –

+0

IMO根本不復雜,並且在Python _readability counts_中。我想我們對複雜有不同的定義。 – nutmeg64

+0

我的觀點是你的默認語句(#3)是錯誤的。至於「複雜」:它確實使普通案例簡潔易讀,但它是魔術和非正交的,我認爲這是值得稱道的。 –

相關問題