사전, 세트의 데이터 구조에 대한 공부를 하였다.

내용이 많아서 소스코드로 올리지 못한다....


===================================== Python =====================================
##### 사전형(dictionary type) 자료구조
### 딕셔너리의 형식
# 딕셔너리의 표현
a = {'id''min''name''song'}
a['name'# 키로 값을 불러온다. 결과는 'song'.
a = {525626}
a[5# int를 키로 넣을 수 있다. 결과는 25.
a = {id123# 내장 함수를 키로 넣으면 오류는 안 난다.
# {<built-in function id>: 123}. id는 내장함수라서 이런 결과가 나왔다. 응용: 키에 람다식 같은 것을 넣을 수 있다는 뜻.
a = {: [1,2,3]} # 숫자를 키로 잡거나 리스트를 값으로 넣을 수도 있다. 다른 데이터구조도 가능.

# dict(). 내장 함수의 이용.
dict(aa=1# dict() 내장함수는 String으로 지정하지 않더라도 자동으로 키에 String으로 들어간다. {'aa': 1}
# dict('aa'=1) # 키에 String으로 넣으니 에러 발생. SyntaxError: keyword can't be an expression
# dict(1=aa) # 키에 int를 넣으니 에러 발생. SyntaxError: keyword can't be an expression
dict(one=1two=2# {'one': 1, 'two': 2}. 두 개의 데이터를 한 번에 넣을 수 있다.
dict([(1,'one' ),('two',2)]) # {1: 'one', 'two': 2}. 리스트에 튜플 형식으로 쌍을 묶으면 사전타입으로 바꿀 수 있다.
dict({1:'one''two':2}) # {1: 'one', 'two': 2}. 원래 사전 타입을 넣어도 된다.

# zip(). 내장 함수의 이용.
a = ['one''two''three']
b = (123)
dict(zip(a, b)) # {'three': 3, 'one': 1, 'two': 2}. 패킹과 같은 효과이다.
dict(zip(b, a)) # {1: 'one', 2: 'two', 3: 'three'}. 반대의 경우에는 숫자를 키로 넣을 수 있다.
'''리스트 내부의 값이 바뀌었을 때 c,d에 어떤 영향이 있는지 알아보는 실험'''
c = dict(zip(a, b))
d = dict(zip(b, a))
a[0] = 'ha' # 값을 바꿨다.
# ['ha', 'two', 'three']. 출력값 확인.
# {'three': 3, 'one': 1, 'two': 2}. 변화가 없다. 주소가 아닌 값만 복사된 것을 알 수 있다.
# {1: 'one', 2: 'two', 3: 'three'}. 변화가 없다. 주소가 아닌 값만 복사된 것을 알 수 있다.

# 딕셔너리의 연산
a = {'2''2번''3''3번'}
a['1'] = '3번' # a에 키는 '1', 값은 '3번'이라는 요소를 추가했다.
# {'1': '3번', '2': '2번', '3': '3번'}. 내용이 추가된 것을 확인
a['1'] = '1번' # 키가 1인 데이터의 값을 '1번'으로 바꿨다.
# {'1': '1번', '2': '2번', '3': '3번'}. 바뀐 것을 확인
len(a) # 데이터 갯수를 세어주는 length()함수. 결과는 3.

# 딕셔너리의 키 멤버십 테스트
a = {'one'1'two'2'three'3'four'4}
'one' in # a에 키값으로 'one'이 있는지 물어보는 테스트. 결과는 True.
'야호' in # a에 키값으로 '야호'가 있는지 물어보는 테스트. 결과는 False.
in a.values() # a의 값에 1이 있는지 물어보는 테스트. 결과는 True.
100 in a.values() # a의 값에 100이 있는지 물어보는 테스트. 결과는 False.

# 딕셔너리의 포맷팅
a = '%(name)s, %(age)s' # 포맷팅 뿐만 아니라 어느 데이터가 들어가야 하는지도 알려준다.
b = '%(name)s, %(money)s' # 비교를 위해 뒤에 요소를 바꿨다.
a%{'name':'야호''age':'100'# '야호, 100'. 정상적으로 출력된다.
b%{'name':'야호''age':'100'# 에러 발생. TypeError: unsupported operand type(s) for %: 'tuple' and 'dict'

# 딕셔너리의 해시 기법
a={'one':1,'two':2,'three':3,'four':4}
del a ['one'# 키가 'one'인 것을 삭제한다.
# {'three': 3, 'four': 4, 'two': 2}. {'one': 1}이 삭제되었다.
a['one'] = # 삭제된 값을 다시 입력
# {'three': 3, 'four': 4, 'one': 1, 'two': 2}. 제대로 추가된 것을 확인
a[(1,2,3)] = 'tuple' # 튜플 자체를 키로 넣는 것이 가능한지 시도.
# {(1, 2, 3): 'tuple', 'three': 3, 'four': 4, 'one': 1, 'two': 2}. 가능한 것을 확인.
a[[1,2,3]] = 'list' # 리스트 자체를 키로 넣는 것이 가능한지 시도. 리스트는 해쉬화가 불가능하여 에러.
# TypeError: unhashable type: 'list'
a[{'two'2}] = 'dict' # 사전 타입도 해쉬화가 불가능하여 에러. TypeError: unhashable type: 'dict'

### 딕셔너리의 주요 내장 메서드
# keys(). 사전에 들어있는 키를 추출하여 보여준다.
a={'one':1,'two':2,'three':3,'four':4}
a.keys() # dict_keys(['three', 'four', 'one', 'two'])
'''a.keys()가 리스트인지 확인'''
b = a.keys() # b가 리스트인지 확인한다.
type(b) # <class 'dict_keys'>. 'dict_keys'라는 타입이다.
b[1# 리스트가 아니다. 인덱싱을 지원하지 않는다고 나온다. TypeError: 'dict_keys' object does not support indexing

# values(). 사전에 들어있는 값만을 추출하여 보여준다.
a={'one':1,'two':2,'three':3,'four':4}
a.values() # dict_values([3, 4, 1, 2])
'''a.values()가 리스트인지 확인'''
b = a.values() # b가 리스트인지 확인한다.
type(b) # <class 'dict_values'>. 'dict_values'라는 타입이다.
b[1# 리스트가 아니다. 인덱싱을 지원하지 않는다고 나온다. TypeError: 'dict_values' object does not support indexing

# items(). 사전에 어떤 데이터가 있는지 키와 값을 묶어서 보여준다.
a={'one':1,'two':2,'three':3,'four':4}
a.items() # dict_items([('three', 3), ('four', 4), ('one', 1), ('two', 2)])
b = a.items() # 무슨 타입인지 확인하기 위한 처리.
type(b) # <class 'dict_items'>. 'dict_items'타입이다.
b[1# 인덱싱을 지원하지 않는다. TypeError: 'dict_items' object does not support indexing

# .get(a, default). a라는 키를 넣으면 a의 값을 출력한다. 만약 a라는 키가 없으면 default를 출력한다.
a={'one':1,'two':2,'three':3,'four':4}
a.get('one'# 'one'이라는 키에 대한 값을 출력한다. 결과는 1.
a.get('hahaha'# 키가 없으니 출력값도 없다. 결과는 .
a.get('hahaha','그런 키는 없다.'# 키가 없지만 default값이 있으므로 default가 출력된다. 결과는 '그런 키는 없다.'.

# .copy(). .copy()를 이용하면 내용만 복사하여 a가 바뀌어도 b에는 변화가 없다.
a = {'one'1'two'2'three'3'four'4}
b = a # b에 a의 주소값을 할당한다.
a == b # 주소값이 동일하므로 내용도 같다. 결과는 True.
is # 주소값이 동일하므로 결과는 True.
a['five'] = # 값이 추가된다면 어떨까.
a == b # 주소값이 동일하므로 내용도 같다. 결과는 True.
is # 주소값이 동일하므로 결과는 True.
id(a) == id(b) # id가 동일한 것을 확인. True
# {'three': 3, 'five': 5, 'four': 4, 'one': 1, 'two': 2}. 추가된 것을 확인.
# {'three': 3, 'five': 5, 'four': 4, 'one': 1, 'two': 2}. 주소값이 동일하니 추가된 데이터가 b에도 나온다.
c = a.copy() # .copy()를 사용하여 c 객체 생성
# {'three': 3, 'five': 5, 'four': 4, 'one': 1, 'two': 2}.
# {'two': 2, 'five': 5, 'one': 1, 'four': 4, 'three': 3}. a와 동일한 데이터지만 순서가 다르게 나왔다.
a == c # 들어있는 내용이 같으므로 True.
is # 주소값이 달라서 False가 나온다.
id(a) == id(c) # id가 다른 것을 확인. False
del a['five'# a의 값을 지우면 어떤 현상이 일어날까?
# {'three': 3, 'four': 4, 'one': 1, 'two': 2}
# {'three': 3, 'four': 4, 'one': 1, 'two': 2}. a가 변화하니 b도 달라졌다.
# {'two': 2, 'five': 5, 'one': 1, 'four': 4, 'three': 3}. 얘만 그대로이다.
b['five'] = # b에 영향을 주면 a도 바뀔까?
# {'three': 3, 'five': 5, 'four': 4, 'one': 1, 'two': 2}
# {'three': 3, 'five': 5, 'four': 4, 'one': 1, 'two': 2}. a도 바뀌었다.
'''
단순 객체복제: 위에 사용한 b = a. 한 객체를 바꾸면 다른 객체도 동일하게 수정되는 현상을 볼 수 있다.
얕은 복사(shallow copy): 위에 사용한 c = a.copy()
깊은 복사(deep copy): 복합객체를 새롭게 생성하고 그 안의 내용까지 재귀적으로 새롭게 생성하는 복사. 위에 예시는 없다.

*정리
1. 단순복제는 완전히 동일한 객체,
2. 얉은복사(shallow copy)는 복합객체(껍데기)만 복사, 그 내용은 동일한 객체
3. 깊은복사(deep copy)는 복합객체 복사 + 그 내용도 재귀적으로 복사
ref.
보노의 블로그 / 얕은 복사(shallow copy) vs. 깊은 복사(deep copy)
https://blueshw.github.io/2016/01/20/2016-01-20-shallow-copy-deep-copy/
'''

# popitem(). evironment에 저장된 사전 객체의 가장 앞쪽에 있는(인덱스-사전에 인덱스는 없지만-가 가장 낮은) 데이터를
# 출력하고 반환한다.
a={'one':1,'two':2,'three':3,'four':4# {'three': 3, 'four': 4, 'one': 1, 'two': 2} 순서로 저장
a.popitem() # ('three', 3)
a.popitem() # ('four', 4)
a.popitem() # ('one', 1)
a.popitem() # ('two', 2)
# {}

# .pop(key). popitem()과 동일한 효과. popitem()과 다른 점은 키를 입력하여 원하는 값을 나오게 할 수 있다는 점이다.
a={'one':1,'two':2,'three':3,'four':4}
a.pop('one'# 결과는 1.
# {'three': 3, 'four': 4, 'two': 2}. {'one':1}이 사라진 것을 볼 수 있다.

# update(). 사전 타입에 사전 타입을 요소로 집어넣을 때 사용하는
a={'one':1,'two':2,'three':3,'four':4}
b={'five':5}
a.update(b) # a에 b를 사전타입이 아닌 요소로 집어넣는다.
# {'three': 3, 'five': 5, 'four': 4, 'one': 1, 'two': 2}. 제대로 들어간 것을 확인

# clear(). 딕셔너리 내용을 전체 삭제한다.
a={'one':1,'two':2,'three':3,'four':4}
a.clear() # a를 비운다.
# 프로토타입만 남은 것을 확인. 결과는 {}.





##### 세트(set) 자료형
### 세트의 형식
# 세트의 표현
a = set('aabbccdd'# 문자열이 들어가도 중복을 처리한다.
# {'a', 'c', 'd', 'b'}. 중복된 문자를 없애고 각각을 char형태로 출력한다. iterable한 형태는 iterate한다는 것을 알 수 있음.
b = set([1,2,3,4,5,5,5]) # 숫자의 중복도 처리한다.
# {1, 2, 3, 4, 5}. 중복된 숫자를 없애고 출력한다.
c = set((1,2,3,4,5,5,5)) # 튜플이라도 중복을 처리한다.
# {1, 2, 3, 4, 5}. 중복이 없는 것을 확인.
d = set({1:11,2:22,3:33,1:44,2:55,3:66}) # 사전타입이 들어가도 중복을 처리한다.
# {1, 2, 3}.
e = set(['aaaaa''aaaaa']) # 동일한 String이 2개이면서 동시에 내용도 a의 중복이 일어난 경우의 set
# {'aaaaa'}. String 내부의 중복을 허용하는 형태로 출력. iterable 체크는 리스트에서만 한다는 것을 알 수 있다.

# 두 가지 객체가 들어갔을 때 세트의 표현
a=set([1,2,3],[4,5,6]) # set() 안에는 하나의 매개변수만 들어가야 한다. TypeError: set expected at most 1 arguments, got 2
a = set(['aabbccdd''ffgg'])
# {'aabbccdd', 'ffgg'}. 리스트의 경우 iterable한 부분은 리스트로만 간주된다는 것을 알 수 있다.

# 비어있는 세트 표현
a = set() # set에 아무것도 안 넣었다.
# 결과는 set().

# 세트의 시퀀스 자료형 연산
a = set([1,2,3,4,5,6,7,8,9])
a[0# 시퀀스 자료형이 아니므로 인덱싱, 슬라이싱, 정렬 등이 없다. TypeError: 'set' object does not support indexing



### 세트의 연산(집합 관계 연산)
# 합집합
a=set([1,2,3,4])
b=set([3,4,5,6,7,8])
a|b # {1, 2, 3, 4, 5, 6, 7, 8}. 합집합으로 표현.
a.union(b) # {1, 2, 3, 4, 5, 6, 7, 8}. 위와 마찬가지

# 교집합
a=set([1,2,3,4])
b=set([3,4,5,6,7,8])
a & b # {3, 4}. 교집합만 구하였다.
a.intersection(b) # {3, 4}. 위와 마찬가지

# 차집합
a = set([1234])
b = set([345678])
a - b # {1, 2}.
a.difference(b) # {1, 2}.

# 대칭차집합 - 교집합만 제외
a = set([1234])
b = set([345678])
a ^ b # {1, 2, 5, 6, 7, 8}. 교집합을 제외한 값.
a.symmetric_difference(b) # {1, 2, 5, 6, 7, 8}. 위와 동일



### 집합 관계 연산 저장: (원하는 연산 기호)= or _update() <- 이 형태로 가능하다. 의미는 +=, -= 등과 같다.
# 합집합의 저장
a=set([1,2,3,4])
b=set([3,4,5,6,7,8])
a |= b # 합집합 연산의 결과를 a에 저장한다.
a.update(b) # 합집합 연산의 결과를 a에 저장한다.
# 위의 연산 둘 다 {1, 2, 3, 4, 5, 6, 7, 8}라는 결과가 나온다.

# 교집합의 저장
a=set([1,2,3,4])
b=set([3,4,5,6,7,8])
a &= b # 교집합을 a에 저장한다.
a.intersection_update(b) # 교집합을 a에 저장한다.
# 위의 연산 둘 다 {3, 4}.

# 차집합의 저장
a=set([1,2,3,4])
b=set([3,4,5,6,7,8])
a -= b # 차집합의 결과를 a에 저장한다.
a.difference_update(b) # 차집합의 결과를 a에 저장한다.
# {1,2}

# 대칭차집합의 저장
a=set([1,2,3,4])
b=set([3,4,5,6,7,8])
a ^= b # 대칭차집합의 결과를 a에 저장한다.
a.symmetric_difference_update(b) # 대칭차집합의 결과를 a에 저장한다.
# 위의 연산 둘 다 {1, 2, 5, 6, 7, 8}.



### 자료형을 통한 세트 적용
# 세트의 리스트 인덱스. 세트를 리스트로 바꿔서 인덱싱을 할 수 있다.
a = set([112233]) # 리스트 내부의 중복을 제거한다.
b = list(a) # 리스트로 바꿔 인덱싱을 할 수 있다.
# [1, 2, 3].

# 세트의 튜플 인덱스. 세트를 튜플로 바꿔서 인덱싱을 할 수 있다.
a = set((112233)) # 튜플 내부의 중복을 제거한다.
b = list(a) # 리스트로 바꿔 인덱싱을 할 수 있다.
# [1, 2, 3].

# 세트의 멤버십 테스트
a = set([123456789])
in # True
10 not in # True

# 세트를 통한 리스트, 튜플 중복 제거
a = [1,1,2,3,3,2# 내부에 중복이 있다.
set(a) # 내장 함수 set()을 이용하여 중복을 제거하였다. 결과는 {1, 2, 3}.
b=(1,2,3,2,3)
set(b) # 튜플의 중복을 제거하였다. 결과는 {1, 2, 3}



### 세트의 삭제와 동등 비교
# 세트의 삭제
a = set([1,2,3,4,5,6,7,8,9])
del a
# 세트인 a를 지워서 에러가 발생. NameError: name 'a' is not defined

# 동등 비교
a = set([4,5,6,10,20,30])
b = a
a == b # 주소값이 같아서 True.
is # 주소값이 같아서 True.
id(a) == id(b) # True. 주소값이 같기 때문이다.
c = a.copy()
a == c # 값이 같아서 True.
is # 주소값이 다르기 때문에 False.
id(a) == id(c) # 결과는 False. 주소값이 다르다



### 세트의 주요 내장 메서드
# issubset(). 부분집합일 경우 True, 아니면 False를 출력한다.
a = set([4,5,6,10,20,30])
b = set([10,20,30])
b.issubset(a) # b가 a의 부분집합이므로 True.
a.issubset(b) # a가 b의 부분집합이 아니므로 False.
a.issubset(a) # 동일한 경우도 True.

# issuperset(). 상위집합(초집합)의 경우 True, 아니면 False를 출력한다.
a = set([4,5,6,10,20,30])
b = set([10,20,30])
b.issuperset(a) # b가 a의 상위집합이 아니므로 False.
a.issuperset(b) # a가 b의 상위집합이므로 True.
a.issuperset(a) # 동일한 경우도 True.

# union(). 합집합을 연산하여 출력한다.
a = set([4,5,6,10,20,30])
b = set([10,20,30])
b.union(a) # {4, 5, 6, 10, 20, 30}
a.union(b) # {4, 5, 6, 10, 20, 30}

# intersection(). 교집합을 연산하여 출력한다.
a = set([4,5,6,10,20,30])
b = set([10,20,30])
b.intersection(a) # {10,20,30}
a.intersection(b) # {10,20,30}

# difference(). 차집합을 연산하여 출력한다.
a = set([4,5,6,10,20,30])
b = set([10,20,30])
b.difference(a) # set()
a.difference(b) # {4,5,6}

# symmetric_difference(). 대칭차집합을 연산하여 출력한다.
a = set([4,5,6,10,20,30])
b = set([10,20,30])
b.symmetric_difference(a) # {4,5,6}
a.symmetric_difference(b) # {4,5,6}

# update(). 객체의 합집합을 연산하여 객체에 저장한다.
a = set([1234])
b = set([3456])
a.update(b)
# {1, 2, 3, 4, 5, 6}

# intersection_update(). 교집합을 연산하여 객체에 저장한다.
a = set([1234])
b = set([3456])
a.intersection_update(b)
# {3, 4}

# difference_update(). 차집합을 연산하여 객체에 저장한다.
a = set([1234])
b = set([3456])
a.difference_update(b)
# {1, 2}

# symmetric_difference_update(). 대칭 차집합을 연산하여 객체에 저장한다.
a = set([1234])
b = set([3456])
a.symmetric_difference_update(b)
# {1, 2, 5, 6}

# copy(). 얕은 복사(shallow copy)를 한다.
a = set([4,5,6,10,20,30])
b = a.copy( )
# {4,5,6,10,20,30}

# add(). 지정한 원소를 추가한다.
a = set([1,2,3,4])
a.add(7)
# {1, 2, 3, 4, 7}

# remove(). 지정한 원소를 제거한다. 없을 시 오류가 발생한다.
a = set([1,2,3,4])
a.remove(4# 원소를 제거한다.
# {1, 2, 3}
a.remove(4# 없는 원소를 제거하여 에러 발생. KeyError: 4
a.remove() # 원소를 지정하지 않으면 에러가 발생. TypeError: remove() takes exactly one argument (0 given)

# discard(). remove()와 동일한 역할을 한다. 하지만 없는 원소를 제거해도 에러가 안 난다는 특징이 있다.
a = set([1,2,3,4])
a.discard(4)
# {1, 2, 3}
a.discard(4# 에러가 발생하지 않는다.

# pop(). 맨 앞의 원소를 출력하고 반환한다.
a = set([1,2,3,4,5,6,7,8,9])
a.pop() # 맨 앞에 있는 1이 출력되고 반환된다.
# {2,3,4,5,6,7,8,9}
a.pop(4# 지정하는 것은 안 된다. TypeError: pop() takes no arguments (1 given)

# clear(). 모든 원소를 객체에서 제거한다.
a = set([1,2,3,4])
a.clear()
# set()


===================================== Python =====================================

'프로그래밍 > Python, R 프로그래밍' 카테고리의 다른 글

[Python] Python 7일차  (0) 2018.05.18
[R] R 7일차  (0) 2018.05.18
[R] R 6일차  (0) 2018.05.17
[Python] Python 5일차  (0) 2018.05.16
[Python] Python 4일차 - 2  (0) 2018.05.16

+ Recent posts