2017-10-08 72 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)是错误的。至于“复杂”:它确实使普通案例简洁易读,但它是魔术和非正交的,我认为这是值得称道的。 –

相关问题