[Python] list, tuple, dictionary, iterator(map, filter)
- -
알고리즘 문제를 푸는데 자꾸 헷갈리는 파이썬 개념과 메소드들을 정리하려고 한다.
파이썬 자료형 종류와 차이점 - 리스트, 튜플, 딕셔너리
- 리스트
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...등)에 대해서 다룰 예정이다.
'AI 개발' 카테고리의 다른 글
[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 - 함수 정리 (2) | 2020.03.16 |
[Numpy] 딥러닝을 위한 Numpy2 - 행렬의 연산 (0) | 2020.03.10 |
소중한 공감 감사합니다