从txt文件中读取行并创建一个字典,其中的值是元组列表

问题描述

student.txt:

Akçam   Su Tilsim       PSYC 3.9
Aksel   Eda         POLS 2.78
Alpaydin Dilay          ECON 1.2
Atil    Turgut Uluç     IR 2.1
Deveci  Yasemin     PSYC 2.9
Erserçe Yasemin     POLS 3.0
Gülle   Halil       POLS 2.7
Gündogdu Ata Alp    ECON 4.0
Gungor  Muhammed Yasin  POLS 3.1
Hammoud  Rawan      IR 1.7
Has Atakan      POLS 1.97
Ince    Kemal Kahriman  IR 2.0
Kaptan  Deniz       IR 3.5
Kestir  Bengisu     IR 3.8
Koca    Aysu        ECON 2.5
Kolayli Sena Göksu  IR 2.8
Kumman  Gizem       PSYC 2.9
Madenoglu Zeynep    PSYC 3.1
Naghiyeva Gulustan  IR 3.8
Ok  Arda Mert   IR 3.2
Var Berna       ECON 2.9
Yeltekin Sude       PSYC 1.2

您好,我想编写一个函数,该函数文件中有关每个学生的信息读入字典中,字典中的键是部门,值是给定部门中的学生列表(元组列表)。有关每个学生的信息存储在元组中 包含(姓氏,GPA)。文件中的学生可能有多个名字,但只会存储姓氏和gpa。该函数应返回字典。 (姓氏是每行的第一个单词。)

这是我尝试过的:

def read_student(ifile):
    D={}
    f1=open(ifile,'r')
    for line in f1:
        tab=line.find('\t')
        space=line.rfind(' ')
        rtab=line.rfind('\t')
        student_surname=line[0:tab]
        gpa=line[space+1:]
        department=line[rtab+1:space]
        
        if department not in D:
            D[department]=[(student_surname,gpa)]
        else:
            D[department].append((student_surname,gpa))
    f1.close()
    return D
print(read_student('student.txt'))

我认为主要的问题是存在某种混乱,因为有时制表符出现在单词之后,而空格则出现在单词之后,所以我不知道在这种情况下如何正确使用find函数

解决方法

请参阅下文-您将不得不处理姓氏,但问题中的其他详细信息已得到处理

from collections import defaultdict

data = defaultdict(list)
with open('data.txt',encoding="utf-8") as f:
    lines = [l.strip() for l in f.readlines()]
    for line in lines:
        first_space_idx = line.rfind(' ')
        sec_space_idx = line.rfind(' ',first_space_idx - 1)
        grade = line[first_space_idx+1:]
        dep = line[sec_space_idx:first_space_idx]
        student = line[:sec_space_idx].strip()
        data[dep].append((student,grade))
for dep,students in data.items():
    print(f'{dep} --> {students}')

输出

 PSYC --> [('Akçam   Su Tilsim','3.9'),('Deveci  Yasemin','2.9'),('Kumman  Gizem',('Madenoglu Zeynep','3.1'),('Yeltekin Sude','1.2')]
 POLS --> [('Aksel   Eda','2.78'),('Erserçe Yasemin','3.0'),('Gülle   Halil','2.7'),('Gungor  Muhammed Yasin',('Has Atakan','1.97')]
 ECON --> [('Alpaydin Dilay','1.2'),('Gündogdu Ata Alp','4.0'),('Koca    Aysu','2.5'),('Var Berna','2.9')]
 IR --> [('Atil    Turgut Uluç','2.1'),('Hammoud  Rawan','1.7'),('Ince    Kemal Kahriman','2.0'),('Kaptan  Deniz','3.5'),('Kestir  Bengisu','3.8'),('Kolayli Sena Göksu','2.8'),('Naghiyeva Gulustan',('Ok  Arda Mert','3.2')]
,

为什么只用rfind就和findsplit混在一起了?

def read_student(ifile):
    D = {}
    f1 = open(ifile,'r')
    for line in f1:
        cols = line.split() # Splits at one or more whitespace
        surname = cols[0].strip()
        department = cols[-2].strip() # Because you know the last-but-one is dept
        gpa = float(cols[-1].strip()) # Because you know the last one is GPA
        fname = ' '.join(cols[1:-2]).strip() 
        # cols[1:-2] gives you everything starting at col 1 up to but excluding the second-last. 
        # Then you join these with spaces.


        if department not in D:
            D[department] = [(surname,gpa)]
        else:
            D[department].append((surname,gpa))

    f1.close()
    return D

如果您知道自己的列始终用\t分隔,则可以改为使用cols = line.split('\t')。然后,在第二列中有学生的姓名,在第三列中有部门,在第四列中有GPA。

一些建议:

  1. 您可以使用defaultdict来避免每次检查if department not in D
  2. 您可以使用with来管理文件的读取,因此您不必担心f1.close()。这是在Python中读取文件的首选方式。
,

您可以使用rsplit(' ',1)提取姓氏。它给出了包含两个元素的列表。第一个是姓。然后再次拆分第二个元素以使用def read_student(ifile): d = {} with open(ifile) as fp: for line in fp: fname,data = line.strip().split(' ',1) data,gpa = data.rsplit(' ',1) dept = data.split()[-1] d.setdefault(dept,[]).append((fname,gpa)) return d print(read_student('student.txt')) 。它再次给出具有两个元素的列表,第一个是name和dept,第二个是gpa。再次拆分第二个元素以获得部门。

{'ECON': [('Alpaydin',('Gündogdu',('Koca',('Var','2.9')],'IR': [('Atil',('Hammoud',('Ince',('Kaptan',('Kestir',('Kolayli',('Naghiyeva',('Ok','3.2')],'POLS': [('Aksel',('Erserçe',('Gülle',('Gungor',('Has','1.97')],'PSYC': [('Akçam',('Deveci',('Kumman',('Madenoglu',('Yeltekin','1.2')]}

输出:

{{1}}
,

此解决方案利用itemgetter简化了变量的获取:姓氏,部门。和gpa

from operator import itemgetter
d = dict()

with open('f0.txt','r') as f:
    for line in f:
        name,dept,gpa = itemgetter(0,-2,-1)(line.split())
        d.setdefault(dept,[]).append((name,gpa))

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...