파이썬 튜플(Tuple) 집합(셋, Set) 선언 인덱싱 슬라이싱 연산방법

오늘은 또다른 자료구조 형태인 튜플과 셋에 대해 알아본다.

튜플과 셋을 공부하기에 앞서 기본적으로 리스트에 대해서 제대로 이해하고 오는것이 중요하다. 리스트는 다수의 자료를 하나의 변수로 저장하고, 연산, 인덱싱, 슬라이싱을 이용하여 다양한 형태로 추출할 수 있다.

튜플과 셋도 리스트에서의 개념과 함수를 알고 있다면 금새 익힐 수 있으니 리스트와 스택/큐 개념을 먼저 제대로 복습하도록 하자.

튜플 (Tuple)

튜플은 기본적으로 리스트와 동일하게 다룰 수 있다. 한가지 차이점은 값을 바꿀 수 없다는 점이다. 즉, 값이 안바뀌는 리스트라고 생각해도 되겠다.

튜플의 선언

>>> t=(1)
>>> t
1

>>> t=(1,)
>>> t
(1,)

>>> t=("a")
>>> t
'a'

>>> t=("a",)
>>> t
('a',)

튜플을 선언할 때 주의할 점이 있다. 위처럼 숫자 1개만 원소로 덜렁 넣으면, 튜플 데이터 구조가 아닌 그냥 그 숫자로만 인식한다. 그래서 원소를 한개만 지정할 경우 뒤에 콤마를 붙여주어야 한다. 문자형 한개를 원소로 넣는 경우에도 마찬가지이다.

값이 하나인 경우 콤마를 써서 튜플이라는 것을 알려주어야 한다.

리스트 ↔ 튜플 치환

>>> t=(1,2,3)
>>> type(t)
<class 'tuple'>

>>> t=list(t)
>>> type(t)
<class 'list'>
>>> t
[1, 2, 3]

>>> t=tuple(t)
>>> type(t)
<class 'tuple'>
>>> t
(1, 2, 3)

위와같이 list() tuple() 함수를 이용해서 자료형을 서로 변환해줄 수도 있다.

>>> t(0)=1
  File "<stdin>", line 1
    t(0)=1
    ^
SyntaxError: cannot assign to function call
>>> t=list(t)
>>> t[0]=1
>>>

tuple 형태일 때는 원소를 변경하려고 하면 에러메세지가 뜨지만 리스트 형으로 치환한 후에는 변경이 가능함을 알 수 있다.

튜플 연산과 인덱싱/슬라이싱

>>> t+t
(1, 2, 3, 1, 2, 3)
>>> t*2
(1, 2, 3, 1, 2, 3)
>>>

위와 같이 더하기 곱하기를 통한 연산은 리스트와 동일하게 이루어진다.

>>> t=(1,2,3)
>>> t[0]
1
>>> t[0:1]
(1,)
>>> t[0:0]
()
>>> t[1]
2

>>> t=list(t)
>>> t[0]
1
>>> t[0:1]
[1]
>>> t[0:0]
[]
>>> t[1]
2

인덱싱과 슬라이싱도 리스트처럼 할 수 있다.

여기서도 특이한 점은 리스트와 튜플 모두 한개 주소만 인덱싱 하면 괄호가 없는 정수 하나가 출력되었다.

t[0] = 1

반면 t[0:1] 으로 0번째 원소 1개만 포함하도록 슬라이싱할 경우 리스트는 괄호가 붙어서 [1]로 나오지만 튜플은 (1,)으로 나온다. 원소 1개가 있는 튜플은 반드시 콤마를 포함해야 한다는 것을 이렇게 역으로 보여준 것이다.

튜플을 사용하는 이유❓❓

파이썬 프로그램을 작동하는 동안 변경되지 않는 데이터를 저장하는 목적이다. 프로그래밍을 여럿이 같이 작업할 경우, 이 변수로 지정한 데이터 구조체는 바꾸지 말아야 하는 값이라고 튜플로 지정해 놓아서 혼선을 피하는 것이다.

집합 (Set)

또다른 데이터 구조인 집합(Set)은 중복을 불허하는 집합 형태이다. 리스트는 [] 튜플은 () 괄호를 통해 선언한 것과 달리 셋은 set 이라고 써서 선언을 해주어야 한다.

집합의 선언과 수정

>>> s=set([1,2,3,4])
>>> s
{1, 2, 3, 4}

>>> s={1,2,3,4}
>>> s
{1, 2, 3, 4}

>>> s.add(5)
>>> s
{1, 2, 3, 4, 5}

>>> s.remove(1)
>>> s
{2, 3, 4, 5}

>>> s.update([1,6,7])
>>> s
{2, 3, 4, 5, 1, 6, 7}

>>> s.discard(1)
>>> s
{2, 3, 4, 5, 6, 7}

>>> s.clear()
>>> s
set()

위와 같이 set([]) 형태 또는 {} 중괄호를 이용해서 선언을 한다. 그리고 다음과 같은 명령어들로 수정해줄 수 있다. 

  • add 추가
  • remove 삭제
  • discard 삭제
  • update 추가
  • clear 전체삭제

여기서 삭제하는 명령어가 두 가지 있는데 무슨 차이일까?

remove는 실제로 있는 값을 지워주는 것이라 없는 값을 지정해주면 에러가 발생한다. 반면에 discard는 없는 값을 지정하더라도 에러가 없이 수행이 된다. remove는 실제로 존재하는 원소(element)를 지울 때, discard는 해당 원소의 존재 유무가 불확실할 때 확실히 제거해주는 목적으로 사용하는 차이가 있다.

셋은 말그대로 집합형 자료구조이기 때문에 이를 통해 집합의 연산을 할 수가 있다.

  • 교집합 & , intersection
  • 합집합 | , union
  • 차집합 – , difference

파이썬 쉘에서의 예제로 어떻게 활용하는지 살펴보자.

## 집합 선언
>>> s1={1,2,3,4,5}
>>> s2={4,5,6,7,8}
>>> s1
{1, 2, 3, 4, 5}
>>> s2
{4, 5, 6, 7, 8}

## 합집합
>>> s1.union(s2)
{1, 2, 3, 4, 5, 6, 7, 8}
>>> s1|s2
{1, 2, 3, 4, 5, 6, 7, 8}

## 교집합
>>> s1.intersection(s2)
{4, 5}
>>> s1&s2
{4, 5}

## 차집합
>>> s1.difference(s2)
{1, 2, 3}
>>> s1-s2
{1, 2, 3}

이를 이용해 서로 다른 데이터 구조체들간에 공통 부분을 추출하거나, 공통 부분을 뺀다던지 하는 연산을 해줄 수 있다.

튜플과 집합 자료구조에 대해 살펴보았고 다음 시간에는 사전 형태에 대해 알아본다.