-
[Python] list, tuple, dictionary, iterator(map, filter)💫 Computer Science/Python & AI Framework 2020. 9. 6. 00:44
알고리즘 문제를 푸는데 자꾸 헷갈리는 파이썬 개념과 메소드들을 정리하려고 한다.
파이썬 자료형 종류와 차이점 - 리스트, 튜플, 딕셔너리
- 리스트
a = [1,2,3,4] b = [1,2,[a,b]]
변수를 여러개 저장할 수 있는 자료구조 중 대표적인 것. 반복문을 통해 데이터 관리가 가능하고 다양한 모양으로 생성할 수 있다. 정수와 문자를 섞어 넣는다던지, 리스트 안에 리스트를 넣는다던지
- 튜플
a = (1,2,3) b = (1,) c = 1,2,3 d = ('a','b',('c','d'))
리스트와 거의 유사하나 차이점은
1개의 요소만을 가질 때 반드시 , 붙여주어야 하고 괄호 생략해도 무방하다는 점 또, 요소의 값을 변경하거나 지울 수 없다. 대신 리스트보다 빠르다. 수정할 필요가 없는 리스트는 튜플로 작성해도 괜찮지만 리스트나 딕셔너리보다 잘 사용하지 않는 것 같다.
- 딕셔너리
a = {'a': 1, 'b': 2} b = {'a':[1,2,3], 'b':[4]} a[a] # 1 b[a] # [1,2,3]
키-쌍 값으로 이루어진 자료구조. 키를 가지고 바로 값을 찾을 수 있어 리스트의 요소의 개수가 많을 때 탐색이 필요하다면 리스트보다 딕셔너리가 훨씬 빠를 수 있다. 대신 인덱스로 접근 할 수 없고 키 값으로만 접근 가능.
1. 리스트 사용하기
- 리스트 조작 메서드 : append, extend, insert
a = [1,2,3,6] a.append(4) # [1,2,3,6,4]
append는 리스트 끝에 요소 하나를 추가
a = [1,2,3,4] a.append([100,200]) # [1,2,3,4,[100,200]] len(a) # 5
리스트를 append하면 리스트 안에 리스트가 들어가 중첩리스트가 만들어진다. 추가한 1개의 리스트가 1개의 요소이기 때문에 길이는 4+1인 5이다.
a = [1,2,3,4] a.extend([100,200]) # [1,2,3,4,100,200] len(a) # 6
요소를 여러개 추가 하고 싶으면 extend를 사용한다. 리스트끼리 연결을 하는 것이다.
a = [1,2,3,4] a.insert(2, 100) # [1,2,100,3,4]
insert(인덱스, 요소) 파라미터로 준 인덱스 자리에 요소를 추가하고 뒤로 민다.
- 리스트 삭제 메서드 : pop, del, remove
a = [1,2,3,4] a.pop() # [1,2,3] n = a.pop(0) print(a) # [2,3] print(n) # 1
pop()은 파라미터를 지정해주지 않으면 맨 뒤의 요소를 삭제하고 파라미터로 인덱스를 지정해주면 해당 인덱스 요소가 삭제되고 pop한 값을 변수에 넣어 줄 수 있다. DFS, BFS 문제에서 많이 사용한다.
a = [1,2,3,4] del a[1] # [1,3,4]
del과 pop은 비슷하게 동작하나, 지운 리스트 내 요소 값을 따로 사용할 때는 pop()을 사용한다.
a = [10,20,30,40,20] a.remove(20) # [10,30,40,20]
인덱스 말고 원하는 값을 삭제하고 싶을 때는 remove를 사용합니다. 만약 그 값이 여러개라면 처음 값만 삭제함.
※ 참고 deque(덱) 객체
from collections import deque q = deque([[1,[1]]]) print(q) q.append([2,[1,2]]) print(q) qq = deque([1]) print(qq) qq.append(1) print(qq) deque([[1, [1]]]) deque([[1, [1]], [2, [1, 2]]]) deque([1]) deque([1, 1])
리스트로 스택과 큐 만들기는 이전 포스팅 참고
- 리스트 슬라이싱[:]
a = [1,2,3,4,5,6,7] print(a[:3]) # [1,2,3] print(a[2:]) # [3,4,5,6,7] print(a[3:5] # [4,5] print(a[-1]) # 7
리스트명[시작인덱스:끝인덱스] 로 지정해 슬라이싱을 할 수 있고 이렇게 지정하게 되면 (시작인덱스)~(끝인덱스-1)한 값까지 출력됩니다. 인덱스가 -1이란 것은 리스트의 가장 끝 값을 말합니다.
- 기타 메소드
.index(값) : 리스트 안의 값에 해당하는 인덱스를 구한다.
.count(값) : 리스트 안의 값에 해당하는 개수를 구한다.
.reverse() : 리스트 요소의 순서를 반대로 뒤집는다.
.sort() : 리스트의 요소를 정렬, 내림차순으로 정렬하려면 .sort(reverse=True)
.sorted() : sort()와 동일하나 기존의 리스트는 그대로 두고 새 리스트에 정렬한 리스트를 반환
.clear(): del a[:]와 같고 리스트의 모든 요소를 삭제한다.
if not 리스트, if 리스트 : 리스트가 비어있는지 조건 확인할 때.
- 2차원 리스트 초기화
# 2*5리스트 만들기 2행 5열 lis = [[0]*5 for _ in range(2)] print(lis) # [[0,0,0,0,0],[0,0,0,0,0]] liss = [[i for i in range(3)] for _ in range(3)] print(liss) # [[0,1,2],[0,1,2],[0,1,2]] lisss = [[0] * i for i in [3, 1, 3, 2, 5]] print(lisss) # [[0, 0, 0], [0], [0, 0, 0], [0, 0], [0, 0, 0, 0, 0]]
- 2차원 리스트 출력
lis = [[i,i+1] for i in range(3)] print(lis) # [[0, 1], [1, 2], [2, 3]] for x, y in lis: print(x,y) # 0 1 # 1 2 # 2 3
- 리스트 중복 제거
lis = [1,1,2,3,3,4,4] lis = list(set(lis)) # [1,2,3,4]
set으로 변환 후 다시 리스트로 변환 하면 되는데, 순서가 뒤죽박죽 된다는 단점이 있다.
순서를 지켜주려면 for 문을 이용해야 한다.
lis = [1,1,2,3,3,4,4] new_lis = [] for li in lis: if li not in new_lis: new_lis.append(li) print(new_lis)
2. 딕셔너리 사용하기
- 딕셔너리 조작 메서드 : setdefault, update, pop
d = {'a': 'aa', 'b': 'bb'} print(d[a]) # aa dd = {i:[i+1,i+2] for i in range(3) print(d) # {0:[1,2], 1:[2,3], 2:[3,4]}
이런 식으로 값을 직접 넣어 딕셔너리를 초기화 할 수도 있지만, (딕셔너리는 append X)
x = {'a': 10, 'b': 20, 'c': 30, 'd': 40} x.setdefault('e') print(x) # {'a': 10, 'b': 20, 'c': 30, 'd': 40, 'e': None} x.setdefault('f',100) print(x) # {'a': 10, 'b': 20, 'c': 30, 'd': 40, 'e': None, 'f':100}
setdefault메소드를 이용할 수도 있습니다. 파미터에 키, 값 순서대로 넣어주면 되는데 만약 값을 지정해주지 않으면 키만 저장하고 값에 None을 저장합니다.
x = {'a': 10, 'b': 20, 'c': 30, 'd': 40} x.update(a=100, d=400) print(x) # {'a': 100, 'b': 20, 'c': 30, 'd': 400} y = {1: 10, 2: 20, 3: 30, 4: 40} y.update({1:100, 3:300}) print(y) # {1: 100, 2: 20, 3: 300, 4: 40} y.update([[2,200], [4,400]) # # {1: 100, 2: 200, 3: 300, 4: 400}
.update는 값을 수정하고 싶을 때 사용하고 키=값을 파라미터로 넣어주면됩니다. 대신 이는 키 값이 문자열일 때만 가능하며 키가 숫자일 때는 update(딕셔너리)를 사용합니다. 또는 [[]]를 이용해 [[키1,값1],...]형식으로 update할 수도 있습니다.
setdefault와 update의 차이점은 setdefault는 이미 들어간 키 값의 수정이 불가능 하지만 update는 가능합니다.
x = {'a': 10, 'b': 20, 'c': 30, 'd': 40} del x['a'] x.pop('b') print(x) # {'c': 30, 'd': 40}
pop과 del은 리스트에서의 사용법과 동일하고, .clear(모든요소삭제)도 동일합니다.
- 그 외 메서드
x = {'a': 10, 'b': 20, 'c': 30, 'd': 40} # 키 값 가져오기 print(x.get('a')) # 10 # 키 값 모두 가져오기 print(x.items()) # dict_items([('a', 10), ('b', 20), ('c', 30), ('d', 40)]) # 키 값 모두 print(x.keys()) # value 값 모두 print(x.values())
3. iteroator를 결과값으로 리턴해주는 내장함수
- map : 반복가능한(iterable) 객체를 받아 각 요소에 함수를 적용해주는 함수이다.
map(적용시킬 함수, 적용시킬 요소)
def add(n): return n+1 a = ['1','2','3','4'] result = map(int, a) result2 = map(add, a) print(result) # [1,2,3,4] print(result2) # [2,3,4,5]
- filter : 특정 조건으로 걸러서 걸러진 요소들로 iterator 객체를 만들어 리턴
filter(적용시킬 함수, 적용시킬 요소)
target = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] result = [] def is_even(n): return True if n % 2 == 0 else False for value in target: if is_even(value): result.append(value) print(result) # [2, 4, 6, 8, 10]
4. 리스트에 map 사용하기
a = [1.2, 2.5, 3.7, 4.6] # map 객체 생성 a = map(int, a) print(a) # <map object at 0x000001A65414B3A0> b = list(map(int, a)) print(b) # [1,2,3,4] c = input().split() # 10 20 (입력) print(c) # ['10', '20'] d = map(int, input().split()) # 10 20 (입력) print(d) # <map object at 0x03DFB0D0> print(list(d)) # [10, 20] a, b = [10, 20] print(a, b) # 10 20 c, d = map(int, input().split()) # 10 20 (입력) print(c, d) # 10 20
d = map(int, input().split()) 로 여러개의 값을 띄어쓰기로 입력 받으면(예를 들어 1 2 3 을 입력했다고 하면) 1 2 3이 들어있는 맵 객체가 d에 들어가고 그대로 출력하게되면 d에 있는 맵 객체의 주소가 출력되고 안의 값을 볼 수 없습니다.
하지만 맵 객체는 iterator 이기 때문에 unpacking(언패킹)이 가능합니다. a,b = [1,2] 로 지정하면 a=1, b=2가 되는 것 처럼 안의 요소들을 각각의 변수로 저장하는 것을 언패킹이라고 합니다.
따라서 a, b = map(int, input().split())으로 지정하면 맵 객체가 반환되는 것이 아니라 각각 언패킹 된 개별의 값이 a와 b에 저장됩니다.
5. 파이썬으로 입력받기 sys.stdin
알고리즘 문제를 풀다보면 입력 값을 input().split()으로 많이 받게 되는데,
그냥 input()과, raw_input()은 파이썬의 sys.stdin으로 입력받는 방법보다 느리다.
a = sys.stdin # ^Z를 입력. 받을 때까지 입력을 받는다. stdin 오브젝트로 반환 a = sys.stdin.readline() # 한 줄 입력. 가장 많이 사용. \n(개행문자)이 붙는다. a = sys.stdin.readline().strip() # \n(개행문자) 자동 삭제 a,b = sys.stdin.readline().split() # 알고리즘 문제 풀 때 많이 사용하는 방법 띄어쓰기 기준으로 나눔
다음 포스팅에서는 문자열을 다루는 방법(strip, replace...등)에 대해서 다룰 예정이다.
'💫 Computer Science > Python & AI Framework' 카테고리의 다른 글
[Python] Effective Python 1 - call by assignment (0) 2021.02.20 [Python] Class & Underscore( _ , __ ) (7) 2020.12.18 [Flask] Heroku에 Flask 배포 (0) 2020.08.11 [Numpy] 딥러닝을 위한 Numpy3 - 함수 정리 (1) 2020.03.16 [Numpy] 딥러닝을 위한 Numpy2 - 행렬의 연산 (0) 2020.03.10