[강의 요약]
[Part 03. 자료구조&알고리즘 with Python_ Ch 02. 자료구조 문제풀이] 강의 수강
44_[연습문제] 튜플 (01)부터 48_[연습문제] 튜플 (05)까지 강의 수강하였음
🐢 100일 챌린지 🔥 : [▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰░ ] 43/100일 (43%)
[44_[연습문제] 튜플 (01)]
튜플은 고정된 데이터를 저장할 때 유용함
리스트로 변환하면 수정/추가 가능하고, 다시 튜플로 변환할 수 있음
▶ 코드 : 자주 접속하는 웹사이트 비번을 튜플에 저장
passwds = ('password1234', 'abc123', 'qwerty', 'letmein', 'welcome00')
print(f'passwds : {passwds}')
[출력 결과]
passwds : ('password1234', 'abc123', 'qwerty', 'letmein', 'welcome00')
▶ 실습 코드
먼저 3학년 총 학점, 평균 계산 및 4학년 목표 학점을 계산하는 코드를 작성
scores = ((3.7, 4.2), (2.9, 4.3), (4.1, 4.2))
total = 0
for s1 in scores:
for s2 in s1:
total += s2
total = round(total, 1)
avg = round((total / 6), 1)
print(f'3학년 총학점: {total}')
print(f'3학년 평균: {avg}')
[출력 결과]
3학년 총학점: 23.4
3학년 평균: 3.9
그다음 4학년 목표 학점, 한 학기 최소학점을 계산하는 코드를 작성
print('-'*60)
grade4TargetScore = round((4.0 * 8 - total), 1)
print(f'4학년 목표 총학점: {grade4TargetScore}')
minScore = round(grade4TargetScore / 2, 1)
print(f'4학년 한학기 최소학점: {minScore}')
[출력 결과]
------------------------------------------------------------
4학년 목표 총학점: 8.6
4학년 한학기 최소학점: 4.3
4학년 1학기 2학기 성적을 튜플로 추가하는 코드를 작성
scores = list(scores) # 튜플 → 리스트 변환
scores.append((minScore, minScore)) # 4학년 1, 2학기 추가
print('-'*60)
scores = tuple(scores) # 다시 튜플 변환
print(f'scores: {scores}')
[출력 결과]
------------------------------------------------------------
scores: ((3.7, 4.2), (2.9, 4.3), (4.1, 4.2), (4.3, 4.3))
[45_[연습문제] 튜플 (02)]
두 개의 튜플을 이용하여 합집합(중복 제거)과 교집합을 구해보는 코드를 구현할 수 있다.
합집합 : 중복 없이 두 튜플을 합쳐서 하나의 튜플로 만든 것
교집합 : 두 튜플 모두에 존재하는 공통 원소들만 추출한 것
주의해야 할 점은 튜플은 변경 불가이므로 리스트 변환 후 조작해야 한다는 것
▶ 코드
튜플을 리스트로 변환 후 합집합과 교집합을 구하는 코드를 작성
tuple1 = (1, 3, 2, 6, 12, 5, 7, 8)
tuple2 = (0, 5, 2, 9, 8, 6, 17, 3)
tempHap = list(tuple1)
tempGyo = list()
for n in tuple2:
if n not in tempHap:
tempHap.append(n)
else:
tempGyo.append(n)
tempHap = tuple(sorted(tempHap))
tempGyo = tuple(sorted(tempGyo))
print(f'합집합(중복X)\t : {tempHap}')
print(f'교집합\t\t : {tempGyo}')
[출력 결과]
합집합(중복X) : (0, 1, 2, 3, 5, 6, 7, 8, 9, 12, 17)
교집합 : (2, 3, 5, 6, 8)
위 문제 다른 풀이 방식.
튜플을 이어인 후 직접 중복 제거 및 교집합 추출하는 코드 작성
tuple1 = (1, 3, 2, 6, 12, 5, 7, 8)
tuple2 = (0, 5, 2, 9, 8, 6, 17, 3)
tempHap = tuple1 + tuple2
print(f'tempHap : {tempHap}')
tempGyo = list()
tempHap = list(tempHap)
print(f'tempHap : {tempHap}')
for n in tempHap:
if tempHap.count(n) > 1:
tempGyo.append(n)
tempHap.remove(n)
print(f'tempHap : {tempHap}')
print(f'합집합(중복X): {tuple(sorted(tempHap))}')
print(f'tempGyo : {tempGyo}')
print(f'교집합 : {tuple(sorted(tempGyo))}')
[출력 결과]
tempHap : (1, 3, 2, 6, 12, 5, 7, 8, 0, 5, 2, 9, 8, 6, 17, 3)
tempHap : [1, 3, 2, 6, 12, 5, 7, 8, 0, 5, 2, 9, 8, 6, 17, 3]
tempHap : [1, 2, 12, 7, 0, 9, 6, 17]
합집합(중복X): (0, 1, 2, 6, 7, 9, 12, 17)
tempGyo : [3, 5, 8, 2, 6, 8, 3]
교집합 : (2, 3, 3, 5, 6, 8, 8)
차이점이 뭘까?
결론부터 말하면 처음 방법이 교집합 결과를 더 깔끔하게 정리할 수 있다.
두 번째 방법은 교집합에 중복원소가 남기 때문에 최종 교집합 정리에는 추가 후처리가 필요할 수 있기 때문이다.
[46_[연습문제] 튜플 (03)]
튜플도 리스트처럼 슬라이싱할 수 있음
튜플의 최솟값, 최댓값을 찾고 인덱스도 구할 수 있음
▶ 코드
numbers = (8.7, 9.0, 9.1, 9.2, 8.6, 9.3, 7.9, 8.1, 8.3)
# 슬라이싱
print(f'numbers[:4] : {numbers[0:4]}') # index 0~3
print(f'numbers[2:5] : {numbers[2:5]}') # index 2~4
print(f'numbers[3:] : {numbers[3:]}') # index 3~
print(f'numbers[2:-1] : {numbers[2:-1]}') # index 2 ~ 뒤에서 두 번째 전까지
print(f'numbers[::3] : {numbers[::3]}') # 전체에서 3칸씩 건너뛰기
# 최솟값/최댓값
print(f'최솟값 : {min(numbers)}')
print(f'최솟값 인덱스 : {numbers.index(min(numbers))}')
print(f'최댓값 : {max(numbers)}')
print(f'최댓값 인덱스 : {numbers.index(max(numbers))}')
[출력 결과]
numbers[:4] : (8.7, 9.0, 9.1, 9.2)
numbers[2:5] : (9.1, 9.2, 8.6)
numbers[3:] : (9.2, 8.6, 9.3, 7.9, 8.1, 8.3)
numbers[2:-1] : (9.1, 9.2, 8.6, 9.3, 7.9, 8.1)
numbers[::3] : (8.7, 9.2, 7.9)
최솟값 : 7.9
최솟값 인덱스 : 6
최댓값 : 9.3
최댓값 인덱스 : 5
▶ 코드
korScore = int(input('국어 점수 입력: '))
engScore = int(input('영어 점수 입력: '))
matScore = int(input('수학 점수 입력: '))
sciScore = int(input('과학 점수 입력: '))
hisScore = int(input('국사 점수 입력: '))
# 점수 저장
scores = (
{'kor': korScore},
{'eng': engScore},
{'mat': matScore},
{'sci': sciScore},
{'his': hisScore}
)
print(f'scores: {scores}')
# 점수 → 학점 변환
for item in scores:
for key in item.keys():
if item[key] >= 90:
item[key] = 'A'
elif item[key] >= 80:
item[key] = 'B'
elif item[key] >= 70:
item[key] = 'C'
elif item[key] >= 60:
item[key] = 'D'
else:
item[key] = 'F'
print(f'scores: {scores}')
[입력]
국어 점수 입력: 85
영어 점수 입력: 92
수학 점수 입력: 77
과학 점수 입력: 88
국사 점수 입력: 59
[출력 결과]
scores: ({'kor': 85}, {'eng': 92}, {'mat': 77}, {'sci': 88}, {'his': 59})
scores: ({'kor': 'B'}, {'eng': 'A'}, {'mat': 'C'}, {'sci': 'B'}, {'his': 'F'})
[47_[연습문제] 튜플 (04)]
강의자료 코드에서는 오름차순 코드만 포함되어 있어서,
내림차순은 개인적으로 추가했음
▶ 코드
[입력]
fruits = ({'수박':8}, {'포도':13}, {'참외':12}, {'사과':17}, {'자두':19}, {'자몽':15})
fruits = list(fruits)
cIdx = 0
nIdx = 1
eIdx = len(fruits) - 1
flag = True
while flag:
curDic = fruits[cIdx]
nextDic = fruits[nIdx]
curDicCnt = list(curDic.values())[0]
nextDicCnt = list(nextDic.values())[0]
if nextDicCnt < curDicCnt:
fruits.insert(cIdx, fruits.pop(nIdx))
nIdx = cIdx + 1
continue
nIdx += 1
if nIdx > eIdx:
cIdx += 1
nIdx = cIdx + 1
if cIdx == 5:
flag = False
print(tuple(fruits))
fruits는 여러 딕셔너리가 들어있는 튜플
리스트로 변환하여 인덱스별로 비교하면서 정렬
cIdx, nIdx를 이동하며 현재 값과 다음 값을 비교하고, 다음 값이 더 작으면 위치를 변경
모든 비교가 끝나면 오름차순으로 정렬된 튜플 출력. 끝
[출력 결과]
({'수박': 8}, {'참외': 12}, {'포도': 13}, {'자몽': 15}, {'사과': 17}, {'자두': 19})
내림차순으로도 정렬해서 출력해 보자.
fruits = ({'수박':8}, {'포도':13}, {'참외':12}, {'사과':17}, {'자두':19}, {'자몽':15})
fruits = list(fruits)
cIdx = 0
nIdx = 1
eIdx = len(fruits) - 1
flag = True
while flag:
curDic = fruits[cIdx]
nextDic = fruits[nIdx]
curDicCnt = list(curDic.values())[0]
nextDicCnt = list(nextDic.values())[0]
if nextDicCnt < curDicCnt:
fruits.insert(cIdx, fruits.pop(nIdx))
nIdx = cIdx + 1
continue
nIdx += 1
if nIdx > eIdx:
cIdx += 1
nIdx = cIdx + 1
if cIdx == 5:
flag = False
print(tuple(fruits))
오름차순에서는 if nextDicCnt < curDicCnt: 비교했지만
내림차순에서는 if nextDicCnt > curDicCnt: 로 비교방향만 반대로 바꿈
비교 방향 하나만 바꾸면 된다는 말이다.
그런데 sorted +_key 활용하는 방법으로도 정렬가능할듯함
[출력 결과]
({'수박': 8}, {'참외': 12}, {'포도': 13}, {'자몽': 15}, {'사과': 17}, {'자두': 19})
[48_[연습문제] 튜플 (05)]
▶ 코드
# 학급별 학생 수 데이터 (튜플 안에 딕셔너리)
studentCnt = (
{'cls01':18},
{'cls02':21},
{'cls03':20},
{'cls04':19},
{'cls05':22},
{'cls06':20},
{'cls07':23},
{'cls08':17}
)
totalCnt = 0
minStdCnt = 0
minCls = ''
maxStdCnt = 0
maxCls = ''
deviation = []
# 데이터 처리
for idx, dic in enumerate(studentCnt):
for k, v in dic.items():
totalCnt += v
if idx == 0 or minStdCnt > v:
minStdCnt = v
minCls = k
if maxStdCnt < v:
maxStdCnt = v
maxCls = k
print(f'전체 학생 수: {totalCnt}명')
avgCnt = totalCnt / len(studentCnt)
print(f'평균 학생 수: {round(avgCnt, 2)}명')
print(f'학생 수가 가장 적은 학급: {minCls}({minStdCnt}명)')
print(f'학생 수가 가장 많은 학급: {maxCls}({maxStdCnt}명)')
for idx, dic in enumerate(studentCnt):
for k, v in dic.items():
deviation.append({k: round(v - avgCnt, 2)})
print(f'학급별 학생 편차: {deviation}')
전체 학생 수 : 각 학급 학생 수 모두 더하기
평균 학생 수 : 전체 학생 수 ÷ 학급 수
최소/최대 학생 수 학급 찾기 : 반복문 안에서 비교
학급별 편차 계산 : 각 학습 학생 수 - 평균값
튜플은 딕셔너리 접근 후 key, value를 분리해서 활용
[출력 결과]
전체 학생 수: 160명
평균 학생 수: 20.0명
학생 수가 가장 적은 학급: cls08(17명)
학생 수가 가장 많은 학급: cls07(23명)
학급별 학생 편차: [{'cls01': -2.0}, {'cls02': 1.0}, {'cls03': 0.0}, {'cls04': -1.0}, {'cls05': 2.0}, {'cls06': 0.0}, {'cls07': 3.0}, {'cls08': -3.0}]
[나의 생각 정리]
튜플은 수정, 추가, 삭제가 불가능해서 데이터 보호가 필요한 경우 사용하면 좋다.
리스트처럼 인덱싱, 슬라이싱, 반복문 활용이 가능해서 다루기 편하다.
대신 값을 바꿔야 할 경우에는 리스트로 변환 후 수정해야 하는 번거로움이 있다.
합집합, 교집합 구현도 가능은 하지만 리스트처럼 자유롭진 않아서 귀찮다.
[적용점]
변경할 필요 없는 데이터는 무조건 튜플로 저장
수정이 필요하면 리스트 변환 후 작업
중복 제거, 합집합/교집합 처리 시 set 자료형을 사용하자
“이 글은 제로베이스 데이터 스쿨 주 3일반 강의 자료 일부를 발췌하여 작성되었습니다.”
'제로베이스 데이터 취업 파트타임 > 100일 챌린지_일일 학습 일지' 카테고리의 다른 글
제로베이스 데이터 파트타임 스쿨 학습 일지 [25.04.30] (0) | 2025.04.30 |
---|---|
제로베이스 데이터 파트타임 스쿨 학습 일지 [25.04.29] (1) | 2025.04.29 |
제로베이스 데이터 파트타임 스쿨 학습 일지 [25.04.27] (0) | 2025.04.27 |
제로베이스 데이터 파트타임 스쿨 학습 일지 [25.04.26] (0) | 2025.04.26 |
제로베이스 데이터 파트타임 스쿨 학습 일지 [25.04.25] (2) | 2025.04.25 |