Processing_data_about_compa.../main.py
teabag 6f01b26dfe итоговая версия проекта
комитить каждую функцию так себе идея учитывая маштабы проекта
2026-04-18 11:38:45 +03:00

261 lines
12 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 1. Читает текстовый файл с данными (каждая строка: имя,отдел,зарплата,стаж).
# Возвращает список словарей: [{"name": str, "dept": str, "salary": float, "exp": float}, ...].
def load_data(filepath: str) -> list[dict]:
employees = []
#filepath = "data/employees.txt"
try:
with open(filepath, "r", encoding="utf-8") as file:
for line_number, line in enumerate(file, 1):
# Чищу строку от пробелов по краям и скипаю пустые строки, а то хз кто там этот емплоес.тииксти писал
line = line.strip()
if not line:
continue
try:
# делим строку по запятой
parts = [p.strip() for p in line.split(",")] # зачем нейронки если всю эту строку мне пайчарм вставил после знака равно???
if len(parts) != 4: # ну вдруг там не 4 колонки
print(f"Ошибка в строке {line_number}: надо 4 значения, а получил {len(parts)}.")
continue
employee = {
"name": parts[0],
"dept": parts[1],
"salary": float(parts[2]),
"exp": float(parts[3])
}
employees.append(employee)
except ValueError as e:
print(f"Ошибка преобразования типов в строке {line_number}: {e}")
except FileNotFoundError:
print(f"Ошибка: Файл по адресу '{filepath}' не найден.")
except Exception as e:
print(f"Произошла непредвиденная ошибка: {e}")
return employees
# 2. Возвращает новый список, содержащий только сотрудников указанного отдела.
def filter_by_department(employees: list[dict], department: str) -> list[dict]:
filtered_list = []
if not isinstance(employees, list):
print("Ошибка: на вход филтру должен подаваться только список")
return []
for emp in employees: # По каждому сотруднику в исходном списке
# чекаем совпадает ли отдел, убираем пробелы и приводим к одному регистру на всякий пожарный
if emp.get ('dept', '').strip().lower() == department.strip().lower():
filtered_list.append(emp)
return filtered_list
# 3. Возвращает новый список с сотрудниками, чей стаж (exp) не меньше min_years.
def filter_by_experience(employees: list[dict], min_years: float) -> list[dict]:
experienced_staff = []
# вдруг там не список
if not isinstance(employees, list):
print("Ошибка: На вход ожидался список сотрудников.")
return []
for emp in employees:
try:
# вытаскиваем стаж и смотрим чтоб не меньше мин ерс
if emp.get('exp', 0) >= min_years:
experienced_staff.append(emp)
except TypeError: # Если в ехр лежит не число
print(f"Ошибка: Некорректный формат стажа у сотрудника {emp.get('name')}")
continue
return experienced_staff
# 4. Вычисляет среднюю зарплату по переданному списку сотрудников. Если список пуст, возвращает 0.0.
def calculate_average_salary(employees: list[dict]) -> float:
# проверяем пустой ли список
if not employees:
return 0.0
total_sum = 0.0
# Сумируем зарплату каждого сотрудника
for emp in employees:
total_sum += emp.get('salary', 0.0) # get чтоб не упасть если ключа нет
average = total_sum / len(employees)
return float(average)
# 5. Возвращает словарь сотрудника с максимальной зарплатой. При пустом списке возвращает None.
def find_highest_paid(employees: list[dict]) -> dict | None:
if not employees:
return None
highest_paid_emp = employees[0]
for emp in employees:
if emp.get("salary", 0) > highest_paid_emp.get('salary', 0):
highest_paid_emp = emp
return highest_paid_emp
# 6. Группирует сотрудников по отделам. Возвращает словарь, где ключ название отдела,
# значение список сотрудников этого отдела.
def group_by_department(employees: list[dict]) -> dict[str, list[dict]]:
departments = {}
for emp in employees:
dept_name = emp.get('dept', 'Unknown')
# если такого отдела нет, создаём для него пустой список
if dept_name not in departments:
departments[dept_name] = []
departments[dept_name].append(emp) # добавляем текущего сотрудника в список его отдела
return departments
# 7. Увеличивает значение salary каждого сотрудника в переданном списке на bonus_percent процентов.
# Изменяет исходные словари (модификация на месте). Функция ничего не возвращает.
def add_bonus(employees: list[dict], bonus_percent: float) -> None:
# в кефах удобнее
multiplier = 1 + (bonus_percent / 100)
for emp in employees:
if "salary" in emp:
emp["salary"] = round(emp["salary"] * multiplier, 2) # раунд тут если чё чтоб не вылезло чудо по типу 0.0000001
# 8. Принимает словарь одного сотрудника, возвращает отформатированную строку:
# "Имя: {name}, Отдел: {dept}, Зарплата: {salary:.2f} руб., Стаж: {exp} лет".
def format_employee_string(employee: dict) -> str:
formatted_str = (
f"Имя: {employee.get('name', 'Не указано')}, "
f"Отдел: {employee.get('dept', 'Не указано')}, "
f"Зарплата: {employee.get('salary', 0.0):.2f} руб., "
f"Стаж: {employee.get('exp', 0)} лет"
)
return formatted_str
# 9. Возвращает новый список сотрудников, отсортированный по зарплате
# (по возрастанию, если reverse=False, иначе по убыванию).
def sort_by_salary(employees: list[dict], reverse: bool = False) -> list[dict]:
if not employees or not isinstance(employees, list): # Если пустой или ваще не список - вернём как есть
return []
sorted_list = sorted(
employees,
key=lambda emp: emp.get('salary', 0.0),
reverse=reverse
)
return sorted_list
# 10. Сохраняет в файл по пути filepath текстовый отчёт:
# для каждого сотрудника строка, полученная функцией format_employee_string().
# Если список пуст, записывает строку "Нет данных".
def save_report(employees: list[dict], filepath: str) -> None:
try:
with open(filepath, "w", encoding="utf-8") as file:
# 1. Если список пуст, пишем "Нет данных"
if not employees:
file.write("Нет данных\n")
else:
# 2. Проходим по каждому сотруднику
for emp in employees:
# Используем твою функцию форматирования
line = format_employee_string(emp)
# Записываем строку и добавляем перенос на новую строку
file.write(line + "\n")
print(f"Отчет успешно сохранен в файл: {filepath}")
except Exception as e:
print(f"Ошибка при сохранении файла: {e}")
def main():
# Главная функция, демонстрирующая работу всех функций обработки данных сотрудников
print("=" * 37)
print("ОБРАБОТКА ДАННЫХ СОТРУДНИКОВ КОМПАНИИ")
print("=" * 37)
# 1. Загружаем данные из файла
filepath = "data/employees.txt"
print(f"\n1. Загрузка данных из файла '{filepath}'...")
employees = load_data(filepath)
print(f" Загружено сотрудников: {len(employees)}")
for emp in employees:
print(f" - {emp['name']}, отдел: {emp['dept']}")
# 2. Демонстрация filter_by_experience - сотрудники со стажем >= 5 лет
print("\n2. Сотрудники со стажем >= 5 лет:")
experienced = filter_by_experience(employees, 5.0)
if experienced:
for emp in experienced:
print(f" - {emp['name']} (стаж: {emp['exp']} лет)")
else:
print(" Нет сотрудников с таким стажем.")
# 3. Фильтруем сотрудников отдела Sales
print("\n3. Фильтрация сотрудников отдела 'Sales'...")
sales_employees = filter_by_department(employees, "Sales")
print(f" Найдено сотрудников в отделе Sales: {len(sales_employees)}")
# 4. Назначаем бонус 10% сотрудникам отдела Sales
print("\n4. Начисление бонуса 10% сотрудникам отдела Sales...")
add_bonus(sales_employees, 10.0)
print(" Бонус начислен. Зарплаты после бонуса:")
for emp in sales_employees:
print(f" - {emp['name']}: {emp['salary']:.2f} руб.")
# 5. Сортируем сотрудников Sales по убыванию зарплаты
print("\n5. Сортировка сотрудников Sales по убыванию зарплаты...")
sorted_sales = sort_by_salary(sales_employees, reverse=True)
print(" Отсортированный список:")
for emp in sorted_sales:
print(f" - {emp['name']}: {emp['salary']:.2f} руб.")
# 6. Вычисляем среднюю зарплату после бонуса
print("\n6. Средняя зарплата в отделе Sales после бонуса:")
avg_salary = calculate_average_salary(sorted_sales)
print(f" {avg_salary:.2f} руб.")
# 7. Находим сотрудника с самой высокой зарплатой
print("\n7. Сотрудник с самой высокой зарплатой в отделе Sales:")
highest_paid = find_highest_paid(sorted_sales)
if highest_paid:
print(f" {highest_paid['name']} - {highest_paid['salary']:.2f} руб.")
# 8. Группируем ВСЕХ сотрудников по отделам и выводим количество
print("\n8. Группировка всех сотрудников по отделам:")
grouped = group_by_department(employees)
for dept, staff in grouped.items():
print(f" Отдел '{dept}': {len(staff)} чел.")
for emp in staff:
print(f" - {emp['name']}")
# 9. Сохраняем итоговый отчёт по отделу Sales
print("\n9. Сохранение отчёта по отделу Sales...")
report_path = "report_sales.txt"
save_report(sorted_sales, report_path)
print("\n" + "=" * 60)
print("ОБРАБОТКА ЗАВЕРШЕНА")
print("=" * 60)
if __name__ == "__main__":
main()