새소식

AI 개발

[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...등)에 대해서 다룰 예정이다.

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.