#python #python-3.x #defaultdict
#python #python-3.x #defaultdict
Вопрос:
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
Здравствуйте, я хочу написать функцию, которая считывает информацию о каждом студенте в файле в словарь, где ключами являются факультеты, а значениями являются список студентов в данном отделе (список кортежей). Информация о каждом студенте хранится в кортеже
содержащий (фамилия, средний балл). У учащихся в файле может быть более одного имени, но будут сохранены только фамилия и средний балл. Функция должна вернуть словарь. (Фамилии — это первые слова в каждой строке.)
Это то, что я пробовал:
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'))
Я думаю, что основная проблема заключается в том, что существует своего рода беспорядок, потому что иногда после слов идет табуляция, а иногда после слов пробел, поэтому я не знаю, как правильно использовать функцию поиска в этом случае.
Комментарии:
1. можете ли вы добавить ожидаемый результат
Ответ №1:
Зачем связываться с rfind
и find
, когда вы можете просто split
?
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')
вместо этого. Тогда у вас есть имя студента во втором столбце, кафедра в третьем и средний балл в четвертом.
Пара предложений:
- Вы можете использовать,
defaultdict
чтобы избежать проверкиif department not in D
каждый раз - Вы можете использовать
with
для управления чтением файла, чтобы вам не приходилось беспокоиться оf1.close()
. Это предпочтительный способ чтения файлов в Python.
Ответ №2:
смотрите ниже — вам нужно будет позаботиться о фамилии, но остальные детали в вопросе были обработаны
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(' ', 0,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', '2.9'), ('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', '3.1'), ('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', '3.8'), ('Ok Arda Mert', '3.2')]
Комментарии:
1. Хотя ответы только для кода могут отвечать на вопрос, вы могли бы значительно улучшить качество своего ответа, предоставив контекст для вашего кода, причину, по которой этот код работает, и некоторые ссылки на документацию для дальнейшего чтения.
Ответ №3:
Вы можете использовать split(' ', 1)
для извлечения фамилии. Это дает список с двумя элементами. первое — фамилия. Затем снова разделите вторые элементы, чтобы получить using rsplit(' ', 1)
. Он снова выдает список с двумя элементами, первый из которых — name и dept, а второй — gpa. Снова разделите второй элемент, чтобы получить отдел.
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'))
Вывод:
{'ECON': [('Alpaydin', '1.2'),
('Gündogdu', '4.0'),
('Koca', '2.5'),
('Var', '2.9')],
'IR': [('Atil', '2.1'),
('Hammoud', '1.7'),
('Ince', '2.0'),
('Kaptan', '3.5'),
('Kestir', '3.8'),
('Kolayli', '2.8'),
('Naghiyeva', '3.8'),
('Ok', '3.2')],
'POLS': [('Aksel', '2.78'),
('Erserçe', '3.0'),
('Gülle', '2.7'),
('Gungor', '3.1'),
('Has', '1.97')],
'PSYC': [('Akçam', '3.9'),
('Deveci', '2.9'),
('Kumman', '2.9'),
('Madenoglu', '3.1'),
('Yeltekin', '1.2')]}
Комментарии:
1. @PranavHosangadi хорошо, сэр
Ответ №4:
Это решение использует itemgetter для упрощения получения переменных: фамилия, отдел. и средний балл
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))
Комментарии:
1. Я никогда не понимал прецедент для
itemgetter
. Кроме краткости, есть ли какая-либо причина предпочестьa, b, c = itemgetter(0, -2, -1)(arr)
вместоa, b, c = arr[0], arr[-2], arr[-1]
?2. @Pranav Hosangadi В этом случае вы могли бы поступить так, как вы объяснили, но его также можно использовать для получения фрагмента хэшей (предоставления искомых ключей) и для получения дополнительных индексов для фрагментов списков (здесь было всего 3 индекса)..
3. Спасибо, теперь я вижу! Поскольку я большую часть времени работаю с массивами numpy, легко забыть, что списки не поддерживают прерывистые фрагменты.