개발자/파이썬 Python

파이선 자료구조 집합 Set 특징, 리얼파이선 15

지구빵집 2022. 2. 28. 09:09
반응형

 

 

파이선의 자료형 Set은 집합을 위한 자료형입니다. 집합은 중복되는 요소가 없고, 순서 없는 컬렉션입니다. 기본적인 용도는 멤버십 검사와 중복 엔트리 제거입니다. 집합 객체는 합집합, 교집합, 차집합, 대칭 차집합과 같은 수학적인 연산들도 지원합니다. 

 

집합의 특징을 간단히 짚어보면

 

  • set() 키워드 혹은 중괄호를 이용합니다.
  • 순서가 없습니다. 순서가 없기 때문에 인덱싱이 불가능합니다.
  • 고유한 값을 가집니다. (값 중복 불가능)
  • mutable(수정 가능한, 값이 변하는) 객체입니다. 

 

파이선 자료구조 집합 Set 특징, 리얼파이선 15 

 

집합을 만들 때는 중괄호나 set() 함수를 사용할 수 있습니다. 주의사항: 빈 집합을 만들려면 set() 을 사용해야 합니다. {} 가 아닙니다; 후자는 빈 딕셔너리를 만드는데, 다음 섹션에서 다룹니다.

 

여기 간략한 예제를 보세요. 

 

>>> basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}

>>> print(basket)                      # 중복된 항목을 제거
{'orange', 'banana', 'pear', 'apple'}

>>> 'orange' in basket                 # 빠른 멤버 검색
True

>>> 'crabgrass' in basket
False

>>> #두 단어에 대해 유일한 글자를 찾는 데모
...
>>> a = set('abracadabra')
>>> b = set('alacazam')
>>> a                                  # unique letters in a
{'a', 'r', 'b', 'c', 'd'}
>>> a - b                              # letters in a but not in b
{'r', 'd', 'b'}
>>> a | b                              # letters in a or b or both
{'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}
>>> a & b                              # letters in both a and b
{'a', 'c'}
>>> a ^ b                              # letters in a or b but not both
{'r', 'd', 'b', 'm', 'z', 'l'}

 

리스트 컴프리헨션과 유사하게, 집합 컴프리헨션도 지원됩니다: 

 

>>> a = {x for x in 'abracadabra' if x not in 'abc'}
>>> a
{'r', 'd'}

 

더욱 분명한 다른 예제를 보시고 set 설명을 이어가겠습니다.

 

# 집합 중복 제거
print('1. 집합 선언시 중복 제거됨')
s1 = {1, 1, 2, 2, 3, 3, 'a', 'a', 'BlockDMask', 'BlockDMask', 'b'}
print(f"s1 : {s1}")
 
 
# 리스트 중복 제거 후 다시 리스트로
print()
print('2. 리스트 중복을 set으로 제거, 그 후 다시 리스트로')
 
result1 = [1, 1, 1, 1, 1, 'a', 'a', 'list', 'list', 1, 1, 1]
print(f'list = {result1}')
 
s2 = set(result1)
print(f'set(리스트) = {s2}')
print(f'list(집합) = {list(s2)}')
 
 
# 튜플 중복 제거 후 다시 리스트로
print()
print('3. 튜플 중복을 set으로 제거, 그 후 다시 리스트로')
 
result2 = (2, 2, 3, 3, 'blog', 'blog', 'blockdmask', 'blockdmask')
print(f'tuple = {result2}')
 
s3 = set(result2)
print(f'set(튜플) = {s3}')
print(f'tuple(집합) = {tuple(s3)}')

 

위 예제코드를 실행하면 아래와 같습니다. 실행은 repl.it 에서 합니다.

 

1. 집합 선언시 중복 제거됨
s1 : {1, 2, 3, 'a', 'BlockDMask', 'b'}

2. 리스트 중복을 set으로 제거, 그 후 다시 리스트로
list = [1, 1, 1, 1, 1, 'a', 'a', 'list', 'list', 1, 1, 1]
set(리스트) = {'a', 1, 'list'}
list(집합) = ['a', 1, 'list']

3. 튜플 중복을 set으로 제거, 그 후 다시 리스트로
tuple = (2, 2, 3, 3, 'blog', 'blog', 'blockdmask', 'blockdmask')
set(튜플) = {'blog', 2, 3, 'blockdmask'}
tuple(집합) = ('blog', 2, 3, 'blockdmask')

 

 

파이썬 집합이란?

 

집합에 관련된 것을 처리하기 위해 만들어진 자료형입니다. set 키워드를 사용하거나 중괄호를 이용해서 표현할 수 있습니다. 아래 예제 코드 3개는 다 같은 집합을 만듭니다.

 

s1 = set({1, 2, 3})
s2 = set([1, 2, 3])
s3 = {1, 2, 3}

 

비어있는 집합을 만들기 위해서는 아래와 같이 사용합니다. 

 

s4 = set()

 

자 이제 set의 정의 부분을 한번보면 위와 같이 선언이 가능하다는 것을 알려주고 있습니다. (파이참 IDE 참고)

 

"set() -> new empty set object"라 하여 set()으로 선언하게 되면 새로운 비어있는 set 객체를 생성한다고 나와있습니다.

 

"set(iterable) -> new set object" 이것을 보면 set을 생성할때 인자로 iterable 한 객체를 집어넣게 되면 그걸 이용해서 set 객체가 생성한다고 나와있습니다. set([1,2,3]), set({1,2,3}) 처럼 선언하는 경우를 말합니다.

 

마지막 줄에는 중요한 set의 특징을 알려줍니다. unordered하고 unique elements하다. 순서가 정해져 있지 않고, 중복되지 않는 고유한 요소들을 가지고 있는 자료형이다.

 

파이썬 교집합, 합집합, 차집합, 집합이 같은지, 다른지

 

집합 자료형은 우리가 수학시간에 배웠던 집합의 특징들을 메서드 혹은 연산자를 통해서 구할 수 있게 만들어져 있습니다. 

 

교집합: 교집합을 구할때는 "intersection" 이라는 메서드를 이용하거나 "&"를 이용하여 집합의 교집합을 구할 수 있습니다. 예제에서 보면 두 집합에서 같은 값이 있는 4, 5가 잘 나온 것을 알 수 있습니다.

 

s1 = set([1, 2, 3, 4, 5])
s2 = set([4, 5, 6, 7, 8])
 
# 교집합 메서드 intersection
print(s1.intersection(s2))
 
# 교집합 연산자 &
print(s1 & s2)

// 결과를 보면

{4, 5}
{4, 5}

 

합집합

 

합집합을 구할때는 "union" 이라는 메서드를 이용하거나 "|" 연산자를 이용하여 구할 수 있습니다. 예제의 결과를 보면 양 집합의 모든 요소가 합쳐져서 새로운 집합이 만들어진 것을 볼 수 있습니다.

 

s1 = set([1, 2, 3, 4, 5])
s2 = set([4, 5, 6, 7, 8])
 
# 합집합 메서드 union
print(s1.union(s2))
 
# 합집합 연산자 |
print(s1 | s2)

// 결과를 보면

{1, 2, 3, 4, 5, 6, 7, 8}
{1, 2, 3, 4, 5, 6, 7, 8}

 

차집합

 

순서가 바뀌어도 상관이 없는 교집합, 합집합과 달리 차집합은 순서가 상관이 있습니다. 차집합을 구할때는 "difference" 메서드를 이용하거나 "-" 연산자를 이용해서 구할 수 있습니다.

 

s1 = set([1, 2, 3, 4, 5])
s2 = set([4, 5, 6, 7, 8])
 
# 차집합 메서드 difference
print(s1.difference(s2))
print(s2.difference(s1))
 
# 차집합 연산자 -
print(s1 - s2)
print(s2 - s1)

# 결과를 보면 

{1, 2, 3}
{8, 6, 7}
{1, 2, 3}
{8, 6, 7}

 

 

집합이 같은지

 

집합은 순서가 상관이 없기 때문에 같은 요소만 들어있다면 같은 집합입니다. 집합의 모든요소가 같을 때'만' 집합이 같은 것입니다.

 

s1 = set([1, 2, 3, 4, 5])
s2 = set([4, 5, 6, 7, 8])
s3 = {1, 2, 3, 4, 5}
 
if s1 == s2:
    print("s1과 s2은 같습니다.")
else:
    print("s1과 s2은 다릅니다.")
 
if s1 == s3:
    print("s1과 s3은 같습니다.")
else:
    print("s1과 s3은 다릅니다.")
 
# 결과는 아래와 같습니다. ^^

s1과 s2은 다릅니다.
s1과 s3은 같습니다.

 

집합이 아예 다른지 (같은 요소가 없다)

 

집합이 다른 것은 사실 요소가 하나라도 다르면 다른것입니다. 그것에 대한검사는 != 으로 할수 있습니다. 하지만, 여기서 확인하고 싶은것은 집합에서 공통된 부분이 하나도 없다. 즉, 교집합이 없다. 즉, 아예 모든 요소가 다 다르다. 태생부터 이놈과 저놈은 공통점이 없는 다른 집합이다. 라는 것을 알고 싶을때 사용하는 것 입니다. 그때 사용하는 메서드는 isdisjoint 입니다.

 

** 부분집합을 구하기 위해서는 issubset 메서드를 이용하면 됩니다.

** 대칭 차집합을 구하기 위해서는 symmetric_difference 메서드 혹은 "^" 연산자를 이용하면 됩니다.

 

s1 = set([1, 2, 3, 4, 5])
s2 = set([4, 5, 6, 7, 8])
s3 = {1, 2, 3, 4, 5}
s4 = {6, 7, 8, 9, 10}
 
if s1.isdisjoint(s2):
    print("s1과 s2은 같은 요소가 하나도 없습니다.")
else:
    print("s1과 s2은 같은 요소가 적어도 하나는 있습니다.")
 
if s1.isdisjoint(s3):
    print("s1과 s3은 같은 요소가 하나도 없습니다.")
else:
    print("s1과 s3은 같은 요소가 적어도 하나는 있습니다.")
 
if s1.isdisjoint(s4):
    print("s1과 s4은 같은 요소가 하나도 없습니다.")
else:
    print("s1과 s4은 같은 요소가 적어도 하나는 있습니다.")
    
    
# 실행 결과는 아래와 같습니다.

s1과 s2은 같은 요소가 적어도 하나는 있습니다.
s1과 s3은 같은 요소가 적어도 하나는 있습니다.
s1과 s4은 같은 요소가 하나도 없습니다.

 

3. 파이썬 집합 메서드 add, update, remove, discard, pop, clear, in, len

 

set add - 요소 추가

 

set.add() 메서드를 이용하면 집합 내부에 원하는 값을 추가할 수 있습니다. 예제에서 확인하셨듯이 중복 값을 넣어도 무시되는 것을 알 수 있습니다. 이는 집합의 특징인 "중복 제거"에 의해 만들어진 결과이며, 중복된 값을 넣어도 오류가 발생하지 않는다는 것을 알 수 있습니다.

 

s = {1, 2, 3}
print(f'set : {s}')
 
s.add('blockdmask')
print(f'set : {s}')
 
s.add('blockdmask') # 중복 값
print(f'set : {s}')
 
s.add(4)
print(f'set : {s}')

# 결과를 보면

set : {1, 2, 3}
set : {1, 2, 3, 'blockdmask'}
set : {1, 2, 3, 'blockdmask'}
set : {1, 2, 3, 4, 'blockdmask'}

 

set update - 요소 여러 개 추가

 

set.update() 메서드를 이용하면 집합의 값을 한 번에 여러 개 추가할 수 있습니다. 자세히 보면 요소를 추가할 때 리스트를 뜻하는 대괄호[] 혹은 집합 자료형을 뜻하는 중괄호{}를 이용해서 추가하는 것을 볼 수 있습니다.

 

s = {1, 2, 3}
print(f'set : {s}')
 
s.update({'a', 'b', 'c'})
print(f'set : {s}')
 
s.update([11, 12, 13])
print(f'set : {s}')

# 실행 결과는 

set : {1, 2, 3}
set : {1, 2, 3, 'a', 'b', 'c'}
set : {1, 2, 3, 'b', 11, 12, 13, 'a', 'c'}

 

 

 

set remove - 특정 요소 제거

 

set.remove() 메서드를 이용하면 집합의 특정 요소를 제거할 수 있습니다. 하지만 지우려는 요소가 집합 안에 없는 경우에는 에러가 발생합니다. 정리하면 set.remoe() 메서드는 아래와 같이 동작합니다.

 

set 내부에 값이 있으면 삭제

set 내부에 값이 없으면 오류

 

s = {'kim', 'lee', 'park', 2, 3, 4}
print(f'집합 : {s}')
 
s.remove("kim")
print(f'집합 : {s}')
 
# 에러 발생
# s.remove("kim")
# print(f'집합 : {s}')

# 결과를 보면 

집합 : {2, 3, 4, 'lee', 'kim', 'park'}
집합 : {2, 3, 4, 'lee', 'park'}

 

set discard - 특정 요소 안전하게 제거

 

이렇게 set.discard() 메서드를 이용하면 안전하게 요소를 제거 할 수 있습니다. 집합의 discard 메서드는 아래와 같이 동작합니다.

 

집합 내부에 값이 있으면 삭제.

집합 내주에 값이 없으면 아무 일도 일어나지 않음.

 

s = {'kim', 'lee', 'park', 2, 3, 4}
print(f'집합 : {s}')
 
s.discard("lee")
print(f'집합 : {s}')
 
s.discard("lee")
print(f'집합 : {s}')


# 결과를 보면

집합 : {'park', 2, 3, 'lee', 4, 'kim'}
집합 : {'park', 2, 3, 4, 'kim'}
집합 : {'park', 2, 3, 4, 'kim'}

 

set pop - 임의의 요소를 갖고 온 후 제거

 

아래 예제 코드에서 보는 것처럼 set.pop() 메서드를 사용하면 set의 임의의 요소 하나를 반환하고, 그 반환한 요소를 set에서 제거합니다.

 

여기서 알아야 할 것은 세 가지입니다.

 

  • set.pop() 함수는 임의의 요소 하나 반환, 반환한 요소 제거
  • 임의의 요소라 하지만 자세히 보면 set 맨 앞에 있는 요소를 pop 하고 제거하는 걸로 보입니다. 하지만 임의의 요소라 하는 게 맞는 게, set 자료형이 순서가 없는 자료형 이기 때문에 맨 앞의 요소라 해도, 그것이 실제로는 순서가 없는 것이므로 임의의 요소라는 것이 맞습니다. 
  • set이 비어있는 상태에서 pop() 메서드를 호출하면 에러가 발생하게 됩니다. 그러므로 len 내장 함수 같은걸 이용해서 집합이 비어있는지 확인한 후에 set.pop() 메서드를 사용하는 것이 안전합니다.

 

s = {'r', 'a', 'n', 'd', 'o', 'm'}
print(f'집합 : {s}')
 
print(f'집합.pop() : {s.pop()}')
print(f'집합 : {s}')
 
print(f'집합.pop() : {s.pop()}')
print(f'집합 : {s}')
 
print(f'집합.pop() : {s.pop()}')
print(f'집합 : {s}')
 
print(f'집합.pop() : {s.pop()}')
print(f'집합 : {s}')
 
print(f'집합.pop() : {s.pop()}')
print(f'집합 : {s}')
 
print(f'집합.pop() : {s.pop()}')
print(f'집합 : {s}')
 
# 이미 비어있는 집합 이므로 pop 불가. error 발생.
# print(f'집합.pop : {s.pop()}')
# print(f'집합 : {s}')

# 결과는 아래와 같다. 아 지겹다. 지겨워.

집합 : {'n', 'o', 'd', 'a', 'm', 'r'}
집합.pop() : n
집합 : {'o', 'd', 'a', 'm', 'r'}
집합.pop() : o
집합 : {'d', 'a', 'm', 'r'}
집합.pop() : d
집합 : {'a', 'm', 'r'}
집합.pop() : a
집합 : {'m', 'r'}
집합.pop() : m
집합 : {'r'}
집합.pop() : r
집합 : set()

 

set clear - 모든 요소 제거

 

집합.clear() 를 이용해서 집합 내부의 모든 요소를 제거할 수 있습니다. 모든 요소를 제거한 집합은 비어있는 집합이 되며, print를 했을 때는 "set()"으로 표현됩니다. len() 으로 집합의 길이를 검사하게 되면 집합의 길이는 0이 나오게 됩니다.

 

s = {'e', 'f', 'g', 11, 12, 13}
print(f'집합 s : {s}')
 
s.clear()
print(f'clear 후 집합 : {s}')

$ 결과는 깨끗~

집합 s : {'f', 11, 12, 13, 'e', 'g'}
clear 후 집합 : set()

 

set in - 내부에 요소가 있는지 확인

 

아래 예제 코드에서 보는 것처럼 파이썬의 in 을 이용해서 집합 내부에 해당 요소가 있는지 확인할 수 있습니다.

 

s = {'a', 'b', 'c', 'd'}
 
if 'a' in s:
    print('집합 s 내부에 "a"가 존재합니다.')
else:
    print('집합 s 내부에 "a"가 존재하지 않습니다.')
 
if 'z' in s:
    print('집합 s 내부에 "z"가 존재합니다.')
else:
    print('집합 s 내부에 "z"가 존재하지 않습니다.')
    
# 실행 결과는 아래와 같습니다.

집합 s 내부에 "a"가 존재합니다.
집합 s 내부에 "z"가 존재하지 않습니다.

 

set len - 집합 길이 확인

 

1,2,3,1,2,3 이 있지만 set으로 만드는 순간 중복이 제거되면서 만들어집니다. 그렇기 때문에 {1,2,3}이라는 집합이 생기고 그것을 len 내장 함수를 이용해서 길이를 구합니다. 이렇게 파이썬의 내장 함수인 len()을 이용해서 집합의 길이를 구할 수 있습니다.

 

# 집합 길이 확인
s = {1, 2, 3, 1, 2, 3}
print(f'집합 : {s}')
print(f'집합의 길이 : {len(s)}')
 
# 결과를 보면

집합 : {1, 2, 3}
집합의 길이 : 3

 

 

참고  

개발자 지망생 

 

 

파이선 자료구조 집합

 

 

 

 

 

반응형