[자료구조] 튜플과 딕셔너리

이수연·2024년 6월 19일
0

튜플(Tuple)

  • 한번 정해진 데이터는 변경할 수 없음. , 아이템 변경이 불가하다는 것이 리스트와의 차이점.
  • 중복된 데이터가 존재할 수 있음.
  • () 이용해서 선언하며, 데이터 구분은 ','를 이용한다.
  • 숫자, 문자열, 논리형 등 모든 기본 데이터를 같이 저장할 수 있다.
    • strs = (3.14, '십', 20, 'one')
  • 튜플에 또 다른 컨테이너 자료형 데이터를 저장할 수 있다.
    • students = ('강호동', '박찬호', ('이용규', '박승철', '김지은'))

튜플 아이템 조회

  • 인덱스 이용
    • 존재하지 않는 인덱스 조회하면 IndexError: tuple index out of range 발생
students = ('강호동', '박찬호', ('이용규', '박승철', '김지은'), '박찬호')

print(students[2])

<Output>
('이용규', '박승철', '김지은')

students = ('강호동', '박찬호', '이용규', '박승철', '김지은', '박찬호')

for i in range(len(students)):
    if i % 2 == 0:
        print(f'짝수 인덱스인 학생: {students[i]}')
    else:
        print(f'홀수 인덱스인 학생: {students[i]}')
        
<Output>
짝수 인덱스인 학생: 강호동
홀수 인덱스인 학생: 박찬호
짝수 인덱스인 학생: 이용규
홀수 인덱스인 학생: 박승철
짝수 인덱스인 학생: 김지은
홀수 인덱스인 학생: 박찬호

in, not in 키워드

  • in, not in 키워드를 이용하면 아이템의 존재 유무를 알 수 있다
  • 실습: 컴퓨터가 1~10까지 5개 난수를 생성한 후, 사용자가 입력한 숫자가 있는지/없는지 출력하는 프로그램 만들기
import random

numC = random.sample(range(1,11), 5)
numUser = int(input('1~10 사이의 숫자 입력: '))

if numUser in numC:
    print('컴퓨터와 동일한 숫자를 뽑았습니다!')
else:
    print('꽝!')
print(f'컴퓨터가 뽑은 숫자: {numC}')
print(f'유저가 뽑은 숫자: {numUser}')

<Output>
1~10 사이의 숫자 입력: 3
컴퓨터와 동일한 숫자를 뽑았습니다!
컴퓨터가 뽑은 숫자: [3, 8, 4, 10, 9]
유저가 뽑은 숫자: 3

len(): 아이템 개수 조회

  • 튜플의 아이템 개수 조회: len()
  • for/while 반목문으로 튜플의 아이템 조회 가능

튜플 결합

  • 덧셈 연산자
  • 리스트의 extend() 함수는 튜플에서는 사용할 수 없음!
  • 실습: 튜플로 나와 친구가 좋아하는 번호를 합치되, 버호가 중복되지 않게 하는 프로그램을 만들자
myFavNum = (1, 3, 5, 7, 9)
friendFavNum = (2, 5, 6, 8, 9)

print(f'내가 좋아하는 숫자: {myFavNum}')
print(f'친구가 좋아하는 숫자: {friendFavNum}')

for num in friendFavNum:
    if num not in myFavNum:
        myFavNum = myFavNum + (num, )  #튜플 + 튜플을 해줘야 하기 때문에 (value, ) 사용
print(f'우리가 좋아하는 숫자: {myFavNum}')

<Output>
내가 좋아하는 숫자: (1, 3, 5, 7, 9)
친구가 좋아하는 숫자: (2, 5, 6, 8, 9)
우리가 좋아하는 숫자: (1, 3, 5, 7, 9, 2, 6, 8)

튜플 슬라이싱: [n:m]

  • [n:m]으로 n 이상 m 미만의 인덱스를 갖는 아이템을 추출
    => 리스트와 동일한 법칙
  • 튜플은 슬라이싱을 이용해서 아이템 변경 불가능
  • 단, 리스트의 특정 아이템을 튜플 아이템으로 변경 가능
students = ['강호동', '박찬호', '이용규', '박승철', '김지은', '박찬호']
students[1:4] = (0, 1, 2)
print(students)
print(type(students))

<Output>
['강호동', 0, 1, 2, '김지은', '박찬호']
<class 'list'>
  • slice() 함수로 아이템 슬라이싱
students = ['강호동', '박찬호', '이용규', '박승철', '김지은', '박찬호']
print(f'students: {students[slice(2, len(students)-1)]}')
<Output>
students: ['이용규', '박승철', '김지은']

리스트와 튜플 차이점

  • 튜플: 아이템 추가, 변경, 삭제 불가
  • 튜플은 선언 시 괄호 생략이 가능하다
  • 리스트와 튜플은 자료형 변환 가능
students = '강호동', '박찬호', '이용규', '박승철', '김지은', '박찬호'  #(괄호) 생략 -> tuple
print(f'students type: {type(students)}')

listStudents = list(students)
print(f'list(students) type: {type(listStudents)}')

tupleStudents = tuple(listStudents)
print(f'tuple(students) type: {type(tupleStudents)}')

<Output>
students type: <class 'tuple'>
list(students) type: <class 'list'>
tuple(students) type: <class 'tuple'>

튜플 정렬

  • 튜플을 수정이 불가 -> 리스트로 변환 후 정렬
    • list() -> sort() -> tuple()
  • sorted() 함수: 튜플 정렬
    • sorted()는 리스트 자료형을 반환함.
students = '강호동', '박찬호', '이용규', '박승철', '김지은', '박찬호'
sortedStudents = sorted(students)
print(f'sortedStudents type: {sortedStudents} \ ntype: {type(sortedStudents)}')

<Output>
sortedStudents type: ['강호동', '김지은', '박승철', '박찬호', '박찬호', '이용규']
type: <class 'list'>

for문으로 튜플 아이템 자동 참조(=조회)

  • for문을 이용하면 튜플 내부에 또 다른 튜플의 아이템 조회 가능
studentsCnt = ((1, 25), (2, 50), (3, 31))

for i in range(len(studentsCnt)):
    print(f'{studentsCnt[i][0]}학급의 학생수: {studentsCnt[i][1]}')

for classNo, cnt in studentsCnt:
    print(f'{classNo}학급의 학생수: {cnt}')
<Output>
1학급의 학생수: 25
2학급의 학생수: 50
3학급의 학생수: 31

while문으로 튜플 아이템 자동 참조(=조회)

studentsCnt = ((1, 25), (2, 50), (3, 31))
minCnt = 35
n=0
while n < len(studentsCnt):
    if studentsCnt[n][1] > minCnt:
        n+=1
        continue
    print(f'{studentsCnt[n][0]}학급의 학생수 미달: {studentsCnt[n][1]}')
    n += 1
<Output>
1학급의 학생수 미달: 25
3학급의 학생수 미달: 31

딕셔너리(Dictionary)란?

  • 키(key)와 값(value)을 이용해서 자료를 관리
    • 키(key)는 절대 중복되지 않아야 하며(unique), 값(value)은 중복될 수 있다.
  • {중괄호} 이용해서 선언하며, '키:값'의 형태로 아이템을 정의한다.
  • key와 value에는 숫자, 문자, 논리형, 컨테이너 자료형 올 수 있다.
  • 단, key에 immutable값은 올 수 있지만 mutable값은 올 수 없다.
    • immutable: 변경이 불가능한 데이터 -> key에 사용 가능
    • mutable: [리스트], (튜플) -> key에 사용 불가능!
  • get() 함수에 key를 넣어서 출력할 수 있다.
    • get()에는 없는 key값을 넣어서 조회해도 에러가 발생하지 않는다 => 대신 None 출력
students = {'s1': '차은우', 's2': '장원영', 's3': '유재석', 's4': ['주우재', '김풍']}
print(students['s1'])
print(students['s4'])
print(students['s4'][0])
print(students.get('s1'))
print(students.get('s102839'))
<Output>
차은우
['주우재', '김풍']
주우재
차은우
None

딕셔너리 추가

  • 딕셔너리이름[key] = value 형태로 아이템 추가
    • 입력한 key가 이미 존재한다면 기존 value가 수정된다.
myInfo = {}
myInfo['이름'] = '아무개'
myInfo['이메일'] = 'sy@gmail.com'
myInfo['나이'] = 27
myInfo['취미'] = ['영화 관람', '헬스']
print(myInfo)

myInfo['이메일'] = 'hy@naver.com' # 값이 수정됨
print(myInfo)

<Output>
{'이름': '아무개', '이메일': 'sy@gmail.com', '나이': 27, '취미': ['영화 관람', '헬스']}
{'이름': '아무개', '이메일': 'hy@naver.com', '나이': 27, '취미': ['영화 관람', '헬스']}
  • 실습: 0~10 정수에 대한 팩토리얼을 딕셔너리에 추가해 보자.
factorialDic = {}

for i in range(11):
    if i == 0:
        factorialDic[i] = 1
    else:
        for j in range(1, (i+1)):
            factorialDic[i] = factorialDic[i-1] * j
            # 이전 key의 값에다가 j를 곱한 값

print(f'factorialDic: {factorialDic}')

<Output>
factorialDic: {0: 1, 1: 1, 2: 2, 3: 6, 4: 24, 5: 120, 6: 720, 7: 5040, 8: 40320, 9: 362880, 10: 3628800}

keys()와 values()

  • keys()와 values()로 전체 키와 값을 조회할 수 있다.
  • items()로 key와 value를 튜플 형태로 조회할 수 있다.
  • keys(), values(), items() 조회한 후, list()로 변환할 수 있고, 리스트로 변환했다면 for문으로 자동 조회도 할 수 있다.
# 가장 많이 쓰이는 방법 -> keys()와 반복문 사용해서 전체 데이터 조회
myInfo = {'이름': '아무개', '이메일': 'sy@gmail.com', '나이': 27, '취미': ['영화 관람', '헬스']}
for key in myInfo:
    print(f'{key}: {myInfo[key]}')

<Output>
이름: 아무개
이메일: sy@gmail.com
나이: 27
취미: ['영화 관람', '헬스']
  • 실습: 60점 미만이면 'F(재시험)'으로 값을 변경하는 코드를 keys()를 이용해서 작성해보자.
scores = {'kor': 88, 'eng': 55, 'mat': 85}
print(f'scores: {scores}')

minScore = 60
str = 'F(재시험)'
for key in scores.keys():
    if scores[key] < 60:
        scores[key] = str

print(scores)

<Output>
scores: {'kor': 88, 'eng': 55, 'mat': 85}
{'kor': 88, 'eng': 'F(재시험)', 'mat': 85}

딕셔너리 아이템 삭제하는 방법: del, pop()

  • del 딕셔너리이름[key] => key:value 쌍의 아이템 전체 삭제
  • pop(key) -> key:value 쌍의 아이템 전체 삭제
    • pop(key)의 반환값은 삭제하는 key에 해당하는 value(값)임.
myInfo = {'이름': '아무개', '이메일': 'sy@gmail.com', '나이': 27, '취미': ['영화 관람', '헬스']}

del myInfo['이메일']
print(myInfo)

rValue = myInfo.pop('나이')
print(f'rValue: {rValue}')
print(f'myInfo: {myInfo}')

<Output>
{'이름': '아무개', '나이': 27, '취미': ['영화 관람', '헬스']}
rValue: 27
myInfo: {'이름': '아무개', '취미': ['영화 관람', '헬스']}

in, len(), clear()

  • in, not in: key 존재 유무 판단
  • len(): 딕셔너리 길이 조회
  • clear(): 전체 값 삭제
myInfo = {'이름': '아무개', '이메일': 'sy@gmail.com', '나이': 27, '취미': ['영화 관람', '헬스']}
print('이름' in myInfo)
print('이름' not in myInfo)
print('주소' in myInfo)

print('len(myInfo): {}'.format(len(myInfo)))

print(f'myInfo: {myInfo.clear()}')
print(myInfo)

<Output>
True
False
False
len(myInfo): 4
myInfo: None
{}
  • 실습: 개인정보에 '연락처'와 '주민등록번호'가 있다면 삭제하는 코드 작성하기
myInfo = {'이름': '아무개', '이메일': 'sy@gmail.com', '연락처': '010-0000-2222', '나이': 27, '주민등록번호': '201201-234121', '취미': ['영화 관람', '헬스']}
deleteKeys = ['연락처', '주민등록번호']

for item in deleteKeys:
    if item in myInfo: #in: key 존재 유무 판단
        del myInfo[item]
print(myInfo)
print(len(myInfo))

<Output>
{'이름': '아무개', '이메일': 'sy@gmail.com', '나이': 27, '취미': ['영화 관람', '헬스']}
4

0개의 댓글