[부스트캠프 AI Tech 5기 Pre-Course] 1-1. Python Data Structure

bee·2023년 1월 12일
post-thumbnail

해당 시리즈의 모든 포스팅은 TeamLab Director 최성철 교수님의 부스트캠프 pre-course 강의 내용입니다.

부스트캠프 AI Tech의 Pre-Course를 수강하면서 강의 내용도 정리하고 까먹지 않을겸 벨로그에 차곡차곡 쌓아나가보려고 한다.

1일차-(1)의 강의 주제는 Python Data Structure (파이썬에서 많이 사용되는 자료구조) 이다.

** 자료구조란 ?
어떤 데이터를 저장할 때, 그 데이터에 특징에 따라 컴퓨터에 효율적으로 정리하기 위한 데이터의 저장 및 표현방식을 말한다.


파이썬 데이터 구조

  • 스택(Stack) & 큐(Queue)
  • 튜플(Tuple) & 집합(Set)
  • 사전(Dictionary)
  • Collection 모듈

1) 스택

  • 나중에 넣은 데이터를 먼저 반환하도록 설계된 메모리 구조
  • Last In First Out (LIFO)
  • Push : 스택에 데이터를 입력
  • Pop : 스택에서 데이터를 출력

스택 (Stack) with list object

  • 리스트를 사용하여 스택 구조를 구현할 수 있따.
  • push => append()
  • pop => pop()
    (return이 존재하면서도
>>> a = [1, 2, 3, 4, 5]
>>> a
[1, 2, 3, 4, 5]

>>> a.append(10)
>>> a
[1, 2, 3, 4, 5, 10]

>>> c = a.pop() # 10 출력
>>> a
[1, 2, 3, 4, 5]
## 예제 - 스택 구조를 활용, 입력된 글자를 역순으로 출력
word = input("Input a word : ")
word_list = list(word) # String to List
# print(word_list)
for _ in range(len(word_list)):
	print(word_list.pop())
    print(word_list)
    
## 출력
Input a word : naver
r
['n', 'a', 'v', 'e']
e
['n', 'a', 'v']
v
['n', 'a']
a
['n']
n
[]

2) 큐

  • 스택과 반대의 구조
  • 먼저 넣은 데이터를 먼저 반환하도록 설계된 메모리 구조
  • First In First Out (FIFO)
  • Put : 큐에 데이터를 입력
  • Get : 큐에서 데이터를 출력

큐 (Queue) with list object

  • 파이썬은 리스트를 사용하여 큐 구조를 활용한다.
  • put => append()
  • get => pop(0)
    가장 첫번째 요소를 추출
>>> a = [1, 2, 3, 4, 5]
>>> a.append(10)
[1, 2, 3, 4, 5, 10]

>>> first = a.pop(0) # 첫번째 요소 출력 (FIFO)
>>> a 
[2, 3, 4, 5, 10]
>>> first
1

3) 튜플

  • 값의 변경이 불가능한 리스트
  • 튜플 선언 시 ( ) 를 사용한다.
  • 리스트의 연산, 인덱싱, 슬라이싱 등을 동일하게 사용한다.
>>> t = (1, 2, 3)
>>> t
(1, 2, 3)
>>> type(t)
tuple

>>> t + t
(1, 2, 3, 1, 2, 3)
>>> t * 2 # t값 자체는 변함 없다.
(1, 2, 3, 1, 2, 3)
>>> len(t)
3

>>> t[1]= 5 # 에러 발생 (값을 변경시키려고 했기 때문에)
TypeError : 'tuple' object does not support item assignment

튜플을 사용하는 이유는?

  • 함수의 리턴 값 등 사용자의 실수에 의한 에러를 사전에 방지하기 위해 사용한다.
  • 프로그램을 작동하는 동안 변경되지 않은 데이터의 저장
    ex) 학번, 이름, 우편번호 등등
# 위에 코드 이어서
>>> t = (1) # 일반정수로 인식
>>> type(t)
int

>>> t = (1, ) # 값이 하나이 튜플은 반드시 ","를 붙여야 함
>>> type(t)
tuple

4) 집합

  • 값을 순서없이 저장, 중복을 불허하는 자료형
  • set 객체 선언을 이용하여 객체 생성
>>> s = set([1, 2, 3, 1, 2, 3,])
>>> s
{1, 2, 3} # 중복제거
>>> type(s)
set

>>> a = {1, 2, 3, 4, 5}
>>> type(a)
set

## 기본 연산
>>> b = {2, 3}
>>> b.add(1) # 하나의 원소 1만 추가
>>> b
{1, 2, 3}

>>> b.remove(1) # 1삭제
>>> b
{2, 3}

>>> b.update([1, 4, 5, 6, 7]) # 한번에 여러개를 추가할 때
>>> b
{1, 2, 3, 4, 5, 6, 7}

>>> b.discard(3) # 해당 값만 삭제
>>> b
{1, 2, 4, 5, 6, 7}

>>> b.clear # 모든 원소 삭제
>>> b
{}

>>> s1 = set([1, 2, 3, 4, 5])
>>> s2 = set([3, 4, 5, 6, 7])
>>> type(s1), type(s2)
(set, set)
>>> s1.union(s2) #s1과 s2의 합집합 (= s1 | s2)
{1, 2, 3, 4, 5, 6, 7}
>>> s1.intersection(s2) # s1과 s2의 교집합 (= s1 & s2)
{3, 4, 5}
>>> s1.difference(s2) # s1과 s2의 차집합 (= s1 - s2)
{1, 2}

5) 사전

  • 데이터를 저장 할 때는 구분 지을 수 있는 값을 함께 저장한다.
    ex) 주민등록번호, 제품 모델번호 등
  • Key(또는 Identifier) : 구분을 위한 데이터 고유값
  • 기본형태 : {Key1 : Value1, Key2 : Value2, ...}
  • Key값을 활용하여, 데이터 값(Value)을 관리한다.
  • Key와 Value를 매칭하여 Key로 Value를 검색한다.
  • 다른 언어에서는 Hash Table이라 한다.
>>> country_code = {} # Dict생성, country_code = dict() 도 가능
>>> country_code = {"America" : 1, "Korea" : 82, "China" : 86, "Japan" : 81}
>>> country_code
{"America" : 1, "Korea" : 82, "China" : 86, "Japan" : 81}


>>> country_code.items() # Dict 데이터 ((키, 값)쌍으로) 출력
dict_idems([('America', 1), ('Korea', 82), ('China', 86), ('Japan', 81)])

>>> for dict_items in country_code.items() : # 위와 동일한 의미
		print(dict_items)
('America', 1)
('Korea', 82)
('China', 86)
('Japan', 81)


>>> country_code.keys() # Dict 키 값만 출력
dict_keys(['America', 'Korea', 'China', 'Japan'])


>>> country_code["German"] = 55 # Dict에 추가
>>> country_code
{'America' : 1, 'Korea' : 82, 'China' : 86, 'Japan' : 81, 'German' : 55}


>>> country_code.values() # Dict 데이터 값만 출력
dict_values([1, 82, 86, 81, 55])



>>> for k,v in country_code.items() : 
		print("Key : ", k)
        print("Value : ", v)
Key : America
Value : 1
Key : Korea
Value : 82
Key : China
Value : 86
Key : Japan
Value : 81
Key : German
Value : 55

>>> "Korea" in country_code.keys() # Key값에 "Korea"가 있는지 확인
True

>>> 82 in country_code.values() # Value값에 82가 있는지 확인
True

6) Collections

  • 리스트, 튜플, 딕셔너리에 대한 Python Built-in(파이썬 내장) 확장 자료 구조(모듈)
  • 편의성, 실행효율 등을 사용자에게 제공한다.
  • 아래의 모듈이 존재한다.
from collections import deque
from collections import Counter
from collections import OrderedDict
from collections import defaultdict
from collections import namedtuple

6-1) deque

  • 스택과 큐를 지원하는 모듈
  • 리스트에 비해 효율적인(=빠른) 자료 저장 방식을 지원한다.
  • 링크드 리스트의 특성(rotate, reverse 등)을 지원한다.
  • 기존 리스트 형태의 함수를 모두 지원한다.
>>> from collections import deque

>>> deque_list = deque() # deque 선언

>>> for i in range(5):
		deque_list.append(i)
>>> print(deque_list)
>>> deque.list.appendleft(10) # 요소가 왼쪽에 추가됨
>>> print(deque_list)
deque([10, 0, 1, 2, 3, 4])

>>> deque_list.rotate(2) # 오른쪽으로 2칸씩 회전
>>> deque_list
deque([3, 4, 10, 0, 1, 2])

>>> deque_list.extend([5, 6 ,7]) # 오른쪽에 이어서 추가
>>> deque_list
deque([3, 4, 10, 0, 1, 2, 5, 6, 7])

>>> deque_list.extend([8, 9]) # 왼쪽에 이어서 추가
>>> deque_list
deque([8, 9, 3, 4, 10, 0, 1, 2, 5, 6, 7])
  • deque는 리스트보다 효율적인 자료구조를 제공한다.
  • 효율적 메모리 구조로 처리 속도가 향상된다.
## 일반 리스트
>>> def general_list() : 
		just_list = []
        for i in range(100) :
        	for i in range(100) :
            	just_list.append(i)
                just_list.pop()
>>> %timeit general_list() # 리스트와 비교했을떄 얼마나 빠른지 속도측정

## 데크 리스트
>>> def_deque_list() : 
		deque_lsit = deque()
        
        for i in range(100) : 
        	for i in range(100) : 
            	deque_list.append(i)
                deque_lsit.pop()
>>> %timeit deque_list()

  • 결론 : deque가 일반적인 리스트보다 빠르다!

6-2) OrderedDict

  • Dict와 달리, 데이터를 입력한 순서대로 Dict를 반환한다.
    (그러나 Dict도 python 3.6부터 입력한 순서를 보장하여 출력한다.)
>>> from collections import OrderedDict

>>> d = {}
>>> d['x'] = 100
>>> d['z'] = 300
>>> d['y'] = 200
>>> d['l'] = 500

>>> for k, v in d.items() : 
		print(k, v)
x 100
z 300
y 200
l 500
>>> def get_key(x) : 
		return x[0]

>>> sorted(d.items(), key = lambda t: t[0])
[('l', 500), ('x', 100), ('y', 200), ('z', 300)]

>>> for k, v in OrderedDict(sorted(d.items(), key = lambda t : t[0])).items() : 
		print(k, v)
l 500
x 100
y 200
z 300

6-3) defaultdict

  • Dict 타입의 값에 기본 값을 지정하거나 신규 값을 생성할 때 사용하는 방법
## 에러나는 경우
>>> from collections import defaultdict

>>> d = defaultdict(default_value)
>>> d["first"]
NameError : name 'default_value' si not defined
>>> def default_value() : 
		return 10
        
>>> from collections import defaultdict

>>> d = defaultdict(lambda : 0) # 함수 형태로 바꿔준다
>>> d
defaultdict(<function __main__.<lambda>()>, {})

>>> d["first"]
0
  • 하나의 지문에 각 단어들이 몇 개나 있는지 세고 싶은 경우?
  • Text-mining 접근법 - Vector Space Model

6-4) Counter

  • Sequence 타입의 data element들의 개수를 dict 형태로 반환한다.
>>> from collections import Counter

>>> c = Counter() 
>>> c = Counter('gallahad')
>>> print(c)
Counter({'a' : 3, 'l' : 2, 'g' : 1, 'd' : 1, 'h' : 1})

>>> ball_or_strike_list = ["B", "S", "S", "S", "S", "B", "B"]
>>> c1 = Counter(ball_or_strike_list)
>>> c1
Counter({'B' : 3, 'S' : 4})
  • Dict 타입, keyword 파라미터 등도 모두 처리 가능하다.
  • Set의 연산이 가능하다.
>>> from collections import Counter

>>> c = Counter({'red' : 4, 'blue' : 2})
>>> print(c)
>>> print(list(c.elements()))
['red', 'red', 'red', 'red', 'blue', 'blue']

# Set 연산 지원
>>> c1 = Counter(a = 4, b = 2, c = 0, d = -2)
>>> c2 = Counter(a = 1, b = 2, c = 3, d = 4)
>>> c1.subtract(c2) 
>>> print(c1)
Counter({'a' : 3, 'b' : 0, 'c' : -3, 'd' : -6})

6-5) namedtuple

  • Tuple 형태로 'Data 구조체'를 저장하는 방법
  • 저장되는 데이터의 variable(변수)을 사전에 지정해서 저장한다.
  • 선언 방법 : namedtuple('선언할 이름', [들어갈 값들])
>>> from collecitons import namedtuple
>>> Point = namedtuple('Point', ['x', 'y'])

>>> Point # (oop 개념)
__main__.Point

>>> p = Point(11, y = 22)
>>> p[0], p[1] # unpacking
(11, 22)
>>> p
Point(x = 11, y = 22)

>>> print(p[0] + p[1])

>>> x, y = p
>>> print(x, y)
Point(x = 11, y = 22)

>>> print(p.x + p.y)
33

>>> print(Point(x = 11, y = 22))
Point(x = 11, y = 22)
profile
벌집처럼 밀도있게 차곡차곡 쌓아나가는중

0개의 댓글