줄리아에서 집합 자료형과 연산자
개요
줄리아에서는 파이썬과 마찬가지로 집합 자료형을 지원한다. 원래 집합 자료형이 그렇듯 쓰는 사람은 요긴하게 쓰고 안 쓰는 사람은 일절 사용하지 않는데, 줄리아는 언어 설계 자체가 수학과 가까운만큼 집합의 개념과 연산이 잘 구현되어 있어 반드시 알아두는 게 좋다. 기존의 언어, 특히 파이썬과 가장 다른 점은 유니코드 기호들도 코드의 일부로 사용할 수 있다는 점일 것이다. Atom 에디터에서 Juno를 사용하고 있다면 위와 같이 텍 코드를 자동완성 할 수 있다. 저러한 코드에서 $\in$ 은 단지 기호가 아니라 실제로 원소가 집합에 속하는지를 묘사한다.
코드
julia> X = Set([1,2,3,1]); print(X)
Set([2, 3, 1])
julia> X[1]
ERROR: MethodError: no method matching getindex(::Set{Int64}, ::Int64)
Stacktrace:
[1] top-level scope at REPL[23]:1
julia> for i in X print(i) end
231
위의 코드는 집합 $X$ 를 $X := \left\{ 1, 2, 3, 1 \right\} = \left\{ 2,3,1 \right\}$ 과 같이 정의한 것을 의미한다. 수학에서의 집합이 그러하듯 중복과 순서의 개념이 없다. 따라서 첫번째 인덱스를 참조하면 에러가 뜬다. 그러나 자료형 자체는 파이썬과 비슷하게 이터러블iterable하기 때문에 반복문에서는 사용할 수 있다.
julia> if 1∈X print("!") else print("?") end
!
julia> if 0∈X print("!") else print("?") end
?
julia> if 0∉X print("!") else print("?") end
!
julia> if [1,2] ⊆ X print("!") else print("?") end
!
julia> if [0,1,2] ⊆ X print("!") else print("?") end
?
마치 수식을 읽는 듯한 친숙함이 든다면 집합 자료형을 유용하게 쓸 준비도 되어 있는 것이다. 주목할 것은 딱히 위와 같은 계산들이 집합 자료형에 대해서만 돌아가는 게 아니라는 것이다. 다시 말해, 리스트에 대해서도 같은 연산들을 편하게 사용할 수 있다. 집합 자료형은 어색해도 집합에만 친숙하다면 줄리아의 집합 연산자를 활용하는 데에는 전혀 문제가 없다. 참고로 포함관계는 \susbet $\subset$ 이 아니라 \subseteq $\subseteq$ 을 써야한다.
julia> Y = ["1","2",3]
3-element Array{Any,1}:
"1"
"2"
3
julia> ∪(X,Y)
Set{Any} with 5 elements:
"1"
2
3
"2"
1
julia> ∩(X,Y)
Set{Int64} with 1 element:
3
julia> ∩(Y,X)
1-element Array{Any,1}:
3
julia> setdiff(X,Y); X
Set{Int64} with 3 elements:
2
3
1
julia> setdiff!(X,Y); X
Set{Int64} with 2 elements:
2
1
기본적으로 집합을 다루기 때문에 당연히 합집합과 교집합 역시 수식과 비슷하게 표현할 수 있다. 두번째 줄과 세번째 줄의 차이점은 연산의 순서다. $X$ 는 줄리아에서 집합 자료형, $Y$ 는 그냥 배열로 정의되어있고, 리턴되는 값은 첫번째 인자로 들어오는 데이터의 자료형을 따른다. 이러한 차이점은 줄리아와 같은 강한 타입 언어에서는 아주 중요하므로, 반드시 숙지해두어야한다.차집합은 함수와 모듈 두 가지로 정의되어 있는데, setdiff()
는 그냥 차집합을 반환하고 setdiff!()
는 그 자체만으로 집합을 업데이트 하는 차이점을 확인할 수 있다.
환경
- OS: Windows
- julia: v1.5.0