[ 사전학습 Day 8 ] 성적 관리 시스템 제작하기

sonny·2024년 9월 22일
1

스파르타코딩클럽

목록 보기
10/13
post-thumbnail

오늘 해결해 볼 과제이다.

그저께 collection에 대해 공부해놓길 잘 했다는 생각이 들고, 이참에 성적관리 시스템을 제작하며 컬렉션의 이해를 보다 정확하게 해보려 한다.


학생등록

var students: [String: String] = [:]

학생 목록을 저장하는 변수로 students라는 이름의 빈 Dictionary를 만들고, 이 Dictionary는 학생의 IDkey로, 학생의 이름value로 저장한다.

예를 들어, ["001": "르탄이", "002": "배캠이"] 이런 형태가 된다.

func registerStudent(id: String, name: String) {
    students[id] = name
    print("\(name)(ID: \(id)) 학생이 등록됨")
}

학생을 등록하는 함수인 registerStudent라는 함수를 만들었고, 이 함수는 idname을 받아서 students라는 Dictionary에 학생을 등록한다.

예를 들어, id: "001", name: "르탄이"라면, students["001"]에 "르탄이"를 넣는 것이다.
print는 학생이 등록되었음을 알려주기 위해 콘솔에 메시지를 출력하는 역할을 한다.

registerStudent(id: "001", name: "르탄이")
registerStudent(id: "002", name: "배캠이")
print(students)

이 부분에서는 registerStudent를 실제로 사용해서 "001" ID로 "르탄이", "002" ID로 "배캠이"를 등록한다.

마지막 print(students)students의 내용을 출력하는 것으로, 등록된 학생 목록을 확인할 수 있고, 결과는 ["001": "르탄이", "002": "배캠이"]1 가 된다.

과목 관리

var subjects: [String: Set<String>] = [:]

학생의 과목 목록을 저장하는 변수인 subjects라는 이름의 빈 Dictionary를 만든다. 이 Dictionary는 학생의 이름key로, 학생이 듣는 과목Set으로 저장한다.

예를 들어, ["르탄이": ["수학", "과학"], 배캠이": ["수학", "역사"]] 이런 식으로 과목을 관리한다.

Set<String>을 사용하는 이유는, 학생이 듣는 과목을 중복 없이 관리하기 위해서다.

과목 추가

func addSubject(forStudent name: String, subject: String) {
    if subjects[name] == nil {
        subjects[name] = []
    }
    subjects[name]?.insert(subject)
    print("\(name) 학생에게 \(subject) 과목이 추가됨")
}

과목을 추가하기 위해 name이라는 학생 이름subject라는 과목 이름을 받아서 그 학생의 과목 목록에 과목을 추가한다.

if subjects[name] == nil: 이 부분은 subjects에 그 학생이 아직 등록되지 않았을 경우, 빈 Set을 만들어서 학생을 등록해 준다.

subjects[name]?.insert(subject): 학생의 과목 목록에 새로운 과목을 추가한다.
마지막으로 추가된 내용을 출력해 준다.

if subjects[name] == nil { subjects[name] = [] }Dictionary에서 특정 key가 있는지 확인하고, 없으면 빈 값을 할당하는 코드인데 이 부분을 쉽게 설명하자면, 학생이 아직 과목 목록이 없는 상태일 때, 그 학생에게 빈 과목 목록을 생성해 주는 것이다

과목 삭제

func removeSubject(forStudent name: String, subject: String) {
    subjects[name]?.remove(subject)
    print("\(name) 학생의 \(subject) 과목이 삭제됨")
}

과목 삭제는 학생의 이름과목 이름을 받아서, 해당 과목을 학생의 과목 목록에서 삭제한다. subjects[name]?.remove(subject)로 특정 과목을 지우고, 결과를 출력한다.

subjects[name]?.remove(subject)는, 먼저 subjects라는 Dictionary에서 name이라는 학생의 과목 목록을 찾고, 그 목록에서 subject라는 과목을 제거하는 코드인데,
만약 name이라는 학생이 없거나(subjects[name]이 nil인 경우), 과목 목록이 존재하지 않으면(Set이 nil일 경우), optional chaining(?)에 의해 안전하게 무시돼버린다.

과목 관리

addSubject(forStudent: "르탄이", subject: "수학")
addSubject(forStudent: "르탄이", subject: "과학")
addSubject(forStudent: "르탄이", subject: "영어")
addSubject(forStudent: "배캠이", subject: "수학")
addSubject(forStudent: "배캠이", subject: "역사")

removeSubject(forStudent: "배캠이", subject: "역사")
print(subjects)

위에서 만든 addSubjectremoveSubject 함수를 실제로 호출하여, 르탄이와 배캠이의 과목을 추가하고 삭제한다.

마지막 print(subjects)는 학생들의 과목 목록을 확인할 수 있게 해주는데,
["르탄이": ["수학", "과학", "영어"], "배캠이": ["수학"]] 같은 결과가 나온다.


성적 관리

var grades: [String: [String: [Int]]] = [:]

학생의 성적을 저장하는 grades라는 이름의 Dictionary를 만들고 이 Dictionary는 학생의 이름key로, 학생이 듣는 과목 이름key, 성적을 저장하는 Arrayvalue로 가진다. 예를 들어, ["르탄이": ["수학": [90, 85]]] 이런 식으로 학생의 성적을 관리하게 된다

성적 추가

func addGrade(forStudent name: String, subject: String, grade: Int) {
    if grades[name] == nil {
        grades[name] = [:]
    }
    if grades[name]?[subject] == nil {
        grades[name]?[subject] = []
    }
    grades[name]?[subject]?.append(grade)
    print("\(name) 학생의 \(subject) 과목에 \(grade)점이 추가됨")
}

학생 이름, 과목 이름, 성적을 받아서 성적을 추가한다.
처음 두 개의 if 문은 해당 학생이나 과목이 없으면 빈 데이터를 만들어서 추가할 수 있도록 준비하고, grades[name]?[subject]?.append(grade): 학생의 특정 과목에 성적을 추가한다. 마지막으로 추가된 성적을 출력.

좀 더 자세히 보자면

if grades[name]?[subject] == nil {
    grades[name]?[subject] = []
}

grades[name]?를 사용하여 해당 학생의 과목 데이터를 안전하게 접근하고, grades[name]?[subject]nil이면, 그 학생의 해당 과목에 대한 성적 데이터가 등록되어 있지 않다는 의미이다. 이 경우, 빈 Array를 할당하여 그 과목의 성적 데이터를 초기화하는 것.

grades[name]?[subject]?.append(grade)

이제 학생의 과목에 대한 성적 데이터가 존재하는지 확인한 후, append(grade)를 사용하여 새로운 성적(grade)을 해당 과목의 성적 리스트에 추가한다.

성적 삭제

func removeGrade(forStudent name: String, subject: String, index: Int) {
    grades[name]?[subject]?.remove(at: index)
    print("\(name) 학생의 \(subject) 과목에서 \(index)번째 성적이 삭제됨")
}

학생의 특정 과목에서 index로 지정한 성적을 삭제한다. 예를 들어, 성적이 [90, 85]라면 index 0을 삭제 할 경우, 85만 남게 된다.

grades[name]?

grades는 학생 이름을 key로 하고, 각 과목key로 하여 성적을 Array로 관리하는 Dictionary다.
grades[name]name이라는 학생의 성적 데이터에 접근하는 부분이고 ?optional chaining를 사용하여, 만약 해당 학생의 성적 데이터가 nil인 경우, 이후의 코드를 안전하게 무시하도록 한다.

[subject]?

grades[name]?로 해당 학생의 성적 데이터를 가져온 후, [subject]로 그 학생의 특정 과목에 대한 성적 리스트에 접근한다. 만약 해당 과목이 존재하지 않으면 nil이 반환된다.

?.remove(at: index)

특정 인덱스에 있는 성적을 제거하는 메서드. index는 제거할 성적의 위치를 나타내고, 이 위치에 있는 성적이 삭제된다. 만약 grades[name]?이나 grades[name]?[subject]nil일 경우, 이 메서드는 호출되지 않고 안전하게 무시된다.

성적 관리

addGrade(forStudent: "르탄이", subject: "수학", grade: 90)
addGrade(forStudent: "르탄이", subject: "수학", grade: 85)
addGrade(forStudent: "르탄이", subject: "영어", grade: 70)
addGrade(forStudent: "배캠이", subject: "수학", grade: 75)

removeGrade(forStudent: "배캠이", subject: "수학", index: 0)
print(grades)

이 부분에서는 성적추가하고, 특정 성적삭제하는 작업을 한다. 마지막 print(grades)로 현재 성적 상태를 확인할 수 있다.

결과는 ["르탄이": ["수학": [90, 85], "영어": [70]], "배캠이": ["수학": []]] 같은 형태가 된다.


성적 평균 계산

func calculateAverage(for student: String, subject: String) -> Double? {
    guard let studentGrades = grades[student], 
    let subjectGrades = studentGrades[subject] else {
        return nil
    }
    let total = subjectGrades.reduce(0, +)
    return Double(total) / Double(subjectGrades.count)
}

guard let studentGrades = grades[student], let subjectGrades = studentGrades[subject]: 이 부분은 해당 학생과 과목의 성적이 없을 경우, nil을 반환하도록 한다.
subjectGrades.reduce(0, +): 이 부분은 학생의 성적을 모두 더하는 역할을 하고, 마지막으로 총합을 성적 수로 나누어 평균을 계산한다.

if let average = calculateAverage(for: "르탄이", subject: "수학") {
    print("르탄이의 수학 과목 평균 성적: \(average)점")
} else {
    print("르탄이의 수학 성적을 찾을 수 없습니다.")
}

if let average = calculateAverage(for: "르탄이", subject: "수학"):

calculateAverage 함수는 namesubject매개변수로 받아 해당 학생의 특정 과목 성적 평균을 계산하는 함수다. "르탄이"라는 학생의 "수학" 과목 평균 성적을 계산하려고 호출하는 부분인데,if let은, 함수의 반환값이 옵셔널(즉, 값이 있을 수도 있고 없을 수도 있음)인 경우에 사용된다.

성공적으로 평균을 계산하여 값이 있는 경우, 그 값을 average 상수에 저장한다.만약 성적이 존재하지 않아 nil이 반환되면, if 블록은 실행되지 않고 else 블록으로 넘어간다.

print("르탄이의 수학 과목 평균 성적: \(average)점"):

if 블록이 실행되면, 이 줄이 실행된다.
average 변수를 사용하여 "르탄이""수학" 과목 평균 성적을 출력하고, 문자열 내의 \(average) 부분은 average의 값을 문자열 안에 삽입한다.


후반부 성적 관리 부터는 챗지피티의 도움을 받았다. 아 너무 어렵다.........

처음에는 시스템을 어떻게 구성할지 막막하게 느껴졌고, 여러 가지 복잡한 개념들이 얽혀 있어 정말 어렵게 느껴졌다.

우선, 학생의 성적을 관리하기 위해 필요한 데이터 구조와 로직을 고민하면서 여러 번 시행착오를 겪었지만 그 과정에서 각 기능을 구현하면서 발생하는 문제들을 해결하는 과정이 나에겐 정말 큰 도전이었고, 그만큼 보람도 느낀 것 같다.

전체적인 성적 관리 시스템을 완성하는 데는 시간이 꽤나 많이 걸렸지만, 최종적으로 내가 만든 것이 잘 돌아가고 정상적으로 print 됐을 때 기분이 아주 좋았다. 문제를 해결하는 과정에서 성장도 느끼기도 했고... 앞으로의 과제를 하게 될 때 붙잡고 있으면 어떻게든 해결이 될 것이라는 마음가짐도 갖게 된 듯 하다.

어려운 과정일수록 성장할 수 있는 기회라 여기자.



//학생 등록
var students: [String: String] = [:]


func registerStudent(id: String, name: String) {
    students[id] = name
    print("\(name)(ID: \(id)) 학생이 등록됨")
}


registerStudent(id: "001", name: "르탄이")
registerStudent(id: "002", name: "배캠이")
print(students)

//과목 관리
var subjects: [String: Set<String>] = [:]

//과목 추가
func addSubject(forStudent name: String, subject: String) {
    if subjects[name] == nil {
        subjects[name] = []
    }
    subjects[name]?.insert(subject)
    print("\(name) 학생에게 \(subject) 과목이 추가됨")
}

//과목 삭제
func removeSubject(forStudent name: String, subject: String) {
    subjects[name]?.remove(subject)
    print("\(name) 학생의 \(subject) 과목이 삭제됨")
}

//과목 관리
addSubject(forStudent: "르탄이", subject: "수학")
addSubject(forStudent: "르탄이", subject: "과학")
addSubject(forStudent: "르탄이", subject: "영어")
addSubject(forStudent: "배캠이", subject: "수학")
addSubject(forStudent: "배캠이", subject: "역사")

removeSubject(forStudent: "배캠이", subject: "역사")
print(subjects)

//성적 관리
var grades: [String: [String: [Int]]] = [:]

//성적 추가
func addGrade(forStudent name: String, subject: String, grade: Int) {
    if grades[name] == nil {
        grades[name] = [:]
    }
    if grades[name]?[subject] == nil {
        grades[name]?[subject] = []
    }
    grades[name]?[subject]?.append(grade)
    print("\(name) 학생의 \(subject) 과목에 \(grade)점이 추가됨")
}

//성적 삭제 
func removeGrade(forStudent name: String, subject: String, index: Int) {
    grades[name]?[subject]?.remove(at: index)
    print("\(name) 학생의 \(subject) 과목에서 \(index)번째 성적이 삭제됨")
}

//성적 관리
addGrade(forStudent: "르탄이", subject: "수학", grade: 90)
addGrade(forStudent: "르탄이", subject: "수학", grade: 85)
addGrade(forStudent: "르탄이", subject: "영어", grade: 70)
addGrade(forStudent: "배캠이", subject: "수학", grade: 75)

removeGrade(forStudent: "배캠이", subject: "수학", index: 0)
print(grades)

//성적 평균 계산 
func calculateAverage(for student: String, subject: String) -> Double? {
    guard let studentGrades = grades[student], let subjectGrades = studentGrades[subject] else {
        return nil
    }
    let total = subjectGrades.reduce(0, +)
    return Double(total) / Double(subjectGrades.count)
}


if let average = calculateAverage(for: "르탄이", subject: "수학") {
    print("르탄이의 수학 과목 평균 성적: \(average)점")
} else {
    print("르탄이의 수학 성적을 찾을 수 없음")
}
profile
iOS 좋아. swift 좋아.

1개의 댓글

comment-user-thumbnail
2024년 9월 22일

class로 이용할 경우 https://landelyse.tistory.com/10

답글 달기