반응형

Julia의 데이터 구조(Data structures) - 배열, 튜플, 딕셔너리에 대해 다룹니다.



2023. 12. 02 최초 작성

2023. 12. 10 reshape 예제 추가 


 

다음 사이트를 참고하고 ChatGPT의 도움을 받았습니다. 

https://techytok.com/lesson-data-structures/

https://docs.julialang.org/en/v1/manual/arrays/



 

 

Julia 개발 환경 구축은 다음 포스트를 참고하세요. 

 

Visual Studio Code 사용한 Julia 개발 환경만들기(Windows / Ubuntu / Macbook M1)

https://webnautes.tistory.com/2216 



Julia 강좌를 진행하고 있습니다.

 

Julia 강좌 1 - 변수와 데이터 타입

https://webnautes.tistory.com/2218 

 

Julia 강좌 2 - 함수, void function,  Optional positional arguments, Keyword arguments

https://webnautes.tistory.com/2220 

 

Julia 강좌 3 - 배열, 튜플, 딕셔너리

https://webnautes.tistory.com/2229 

 

Julia 강좌 4 - 제어문 if ... else, for, break, continue, while, enumerate

https://webnautes.tistory.com/2235 

 

Julia 강좌 5 - 브로드캐스팅(broadcasting)

https://webnautes.tistory.com/2240

 

Julia 강좌 6 - 변수 유효 범위( Variable Scope ) : 전역(global), 로컬(local)

https://webnautes.tistory.com/2247

 

Julia 강좌 7 - 모듈(module)

https://webnautes.tistory.com/2253 

 

Julia 강좌 8 - 타입(type)

https://webnautes.tistory.com/2260

 

Julia 강좌 9 - 패키지(package)

https://webnautes.tistory.com/2268 

배열(Arrays)

 

줄리아에서 배열은 0차원(스칼라), 1차원(벡터), 2차원(행렬), 또는 그 이상의 다차원 데이터 구조를 포함하는 더 일반적인 용어입니다. 배열은 Array{T,N}로 표현되며, 여기서 T는 요소의 타입을, N은 배열의 차원을 나타냅니다.

 

1차원 배열 - 벡터(Vectors)

1차원 배열을 벡터(vecotr라고 부릅니다. 줄리아에서 배열은 모든 원소의 데이터 타입이 똑같은 정수(Int), 실수(Float) 등의 단일 데이터 타입으로 구성될 수도 있고 다양한 데이터 타입으로 구성될 수도 있습니다. 



괄호 안에 값을 추가하여 배열을 생성할 수 있습니다.

 

정수 배열입니다.

mat1 = [1, 2, 3]
# 괄호 안에 값을 추가하여 배열을 생성할 수도 있습니다.

# 모든 원소가 정수로 구성되어 있습니다.

println(mat1)
# [1, 2, 3]

display(mat1)
# 3개의 원소로 구성된 Int64 데이터 타입의 벡터라고 출력됩니다.
#
# 3-element Vector{Int64}:
#  1
#  2
#  3



실수 배열입니다.

 

mat1 = [1.1, 2.2, 3.3]
# 괄호 안에 값을 추가하여 배열을 생성할 수도 있습니다.
# 모든 원소가 실수로 구성되어 있습니다.

println(mat1)
# [1.1, 2.2, 3.3]

display(mat1)
# 3개의 원소로 구성된 Float64 데이터 타입의 벡터라고 출력됩니다.
#
# 3-element Vector{Float64}:
#  1.1
#  2.2
#  3.3



정수와 실수가 섞여있는 배열은 실수 배열이 됩니다.

 

mat1 = [1, 2, 5.5]
# 괄호 안에 값을 추가하여 배열을 생성할 수도 있습니다.
# 원소가 정수와 실수로 구성된 경우 모든 원소가 실수로 변환됩니다.

println(mat1)
# [1.0, 2.0, 5.5]

display(mat1)
# 3개의 원소로 구성된 Float64 데이터 타입의 벡터라고 출력됩니다.
#
# 3-element Vector{Float64}:
#  1.0
#  2.0
#  5.5



문자열 배열입니다.

 

mat1 = ["Hello", "it's me", "webnautes"]
# 괄호 안에 값을 추가하여 배열을 생성할 수도 있습니다.
# 모든 원소가 문자열로 구성되어 있습니다.

println(mat1)
# ["Hello", "it's me", "webnautes"]

display(mat1)
# 3개의 원소로 구성된 String 데이터 타입의 벡터라고 출력됩니다.
#
# 3-element Vector{String}:
#  "Hello"
#  "it's me"
#  "webnautes"



정수, 실수, 문자열이 뒤섞여 있는 배열은 Any 데이터 타입의 배열이 됩니다.

 

mat1 =  [1.1, 2, "Hi"
# 괄호 안에 값을 추가하여 배열을 생성할 수도 있습니다.
# 정수와 실수와 문자열이 섞여있는 경우 Any 타입 벡터라고 합니다.

println(mat1)
# Any[1.1, 2, "Hi"]
#
# 배열 앞에 Any가 출력됩니다.

display(mat1)
# 3개의 원소로 구성된 Any 데이터 타입의 벡터라고 출력됩니다.
#
# 3-element Vector{Any}:
#  1.1
#  2
#   "Hi"

mat1 = reshape([i for i in 1:16],4,4)
mat2 = mat1[2:3, 2:3]



괄호를 추가하여 배열을 생성시에도 데이터 타입을 지정할 수 있습니다. 

 

mat1 = Float32[1, 2.3, 4//5]
# 정수와 실수가 섞인 형태의 배열을 생성하면서 데이터 타입으로 Float32를 지정합니다.

println(mat1)
# println 함수는 1차원 배열 형태로 출력합니다.
# Float32[1.0, 2.3, 0.8]

display(mat1)
# 3개의 원소로 구성된 Float32 데이터 타입의 벡터라고 출력됩니다.
#
# 3-element Vector{Float32}:
#  1.0
#  2.3
#  0.8




배열이름[인덱스] 식으로 벡터의 원소에 접근할 수 있습니다.  줄리아는 다른 언어와 달리 인덱스가 1부터 시작합니다. 

 

a = [1, 2, 3, 4, 5# 배열 a는 정수 벡터입니다.

println(a[3])

# 인덱스가 1부터 시작하므로 인덱스 3을 사용하면 벡터 a의 3번째 원소인 3에 접근하게 됩니다.
# a[3]을 출력하면 벡터 a의 3번째 원소인 3이 출력됩니다.
# 3



배열에 원소를 추가하고 싶을 때는 append! 함수와 push! 함수를 사용하면 됩니다. 

 

a = Int[]
# 정수 타입의 빈 벡터를 생성합니다.


# append!는 다른 배열의 원소를 배열에 추가하기 위해 사용됩니다.
append!(a, [1])
# 배열 a에 배열 [1]의 원소를 추가합니다.
println(a)
# [1]

append!(a, [2, 3], [4])
# 배열 a에 배열 [2,3]과 배열 [4]의 원소를 추가합니다.
println(a)
# [1, 2, 3, 4]

b = Int[]

# push!는 개별 원소를 추가하기 위해 사용됩니다.
push!(b, 1)
# 배열 b에 정수 1을 추가합니다.
println(b)
# [1]

push!(b, 2, 3, 4)
# 배열 b에 정수 2,3,4를 추가합니다.
println(b)
# [1, 2, 3, 4]


# 최근 버전의 줄리아에서는 append!도 개별 원소를 추가할 수 있었습니다.
c = [] # 타입을 지정하지 않으면 Any타입의 빈 벡터를 생성합니다.
append!(c, 1)
# 배열 c에 정수 1을 추가합니다.
println(c)
# Any[1]

append!(c, 2, 3, 4)
# 배열 c에 정수 2,3,4를 추가합니다.
println(c)
# Any[1, 2, 3, 4]




벡터의 원소는 같은 타입의 원소로 구성되어 있습니다. 다른 타입의 원소를 추가하려고 하면 에러가 발생합니다. 

 

a = [1, 2, 3# 벡터 a의 타입은 정수입니다.

push!(a, 4.5# 정수 타입 벡터에 실수 값을 추가해봅니다.

print(a)

 



벡터의 타입을 확인하기 위해 typeof 함수를 사용할 수 있습니다. 아래 예제에서 벡터 a가 Any 타입인 것을 확인할 수 있습니다.  이 경우 어떤 타입의 값을 벡터에 추가해도 에러가 발생하지 않습니다.

 

a = [1, 2.3, 's'

println(typeof(a)) # 벡터 a의 타입은 Any입니다.

push!(a, 4.5# Any 타입 벡터에 실수 값을 추가해봅니다.

print(a)

 



2차원 배열 - 행렬(Matrices)

2차원 배열을 행렬(matrix)라고 부릅니다.  세미콜론(;)을 사용하여 행(Row)을 분리하며, 공백을 사용하여 열(Column)을 분리합니다.  다음 예제는 2행 3열의 행렬을 생성합니다. 

 

행렬_이름[행_인덱스, 열_인덱스] 표기법을 사용하여 행렬의 원소에 접근합니다. 예를 들어 행렬 mat의 두번째 행, 세번째 열의 원소에 접근하려면 mat[2,3]을 사용합니다. 

 

mat = [1 2 3; 4 5 6]

# 행렬을 출력해줍니다.
println(mat)
# [1 2 3; 4 5 6]
println(typeof(mat))
# Matrix{Int64}
# Int64 데이터타입의 행렬입니다.
println()

display(mat)
# 2×3 Matrix{Int64}:
#  1  2  3
#  4  5  6
# display 함수를 사용하면 행렬에 대한 자세한 정보를 한번에 보여줍니다.

println(size(mat))
# (2, 3)
# 2행 3열의 행렬이라는 의미로 (2,3)이 출력됩니다.
println()


println(mat[2, 3])
# 6
# 2행 3열에 있는 원소인 6을 출력합니다.




배열 생성 함수 - zeros 

zeros 함수를 사용하여 0으로 채워진 배열을 생성할 수 있습니다. 

 

2행의 배열을 생성하기 위해 튜플 (2)로 지정하고 있습니다. 배열의 디폴트 데이터타입은 Float64입니다. 

 

mat1 = zeros((2))
# 0으로 채워진 2행의 배열을 생성합니다.

println(mat1)
# println 함수는 1차원 배열 형태로 출력합니다.
# [0.0, 0.0]

display(mat1)
# display 함수는 시각적으로 배열 형태를 알아보기 쉽게 출력하며 배열 크기와 데이터 타입도 출력합니다.
# zeros함수로 배열을 생성시 디폴트 데이터 타입은 Float64입니다.
# 2개의 원소로 구성된 Float64 데이터 타입의 벡터라고 출력됩니다.
#
# 2-element Vector{Float64}:
#  0.0
#  0.0



2행 3열의 배열을 생성하기 위해 튜플 (2,3)으로 지정하고 있습니다. 배열의 디폴트 데이터타입은 Float64입니다.

 

mat1 = zeros((2, 3))
# 0으로 채워진 2행 3열의 배열을 생성합니다.

println(mat1)
# println 함수는 1차원 배열 형태로 출력합니다.
#
# [0.0 0.0 0.0; 0.0 0.0 0.0]

display(mat1)
# display 함수는 시각적으로 배열 형태를 알아보기 쉽게 출력하며 배열 크기와 데이터 타입도 출력합니다.
# zeros함수로 배열을 생성시 디폴트 데이터 타입은 Float64입니다.
#
# 2×3 Matrix{Float64}:
#  0.0  0.0  0.0
#  0.0  0.0  0.0



zeros 함수를 사용하여 0으로 채워진 배열을 생성시 데이터타입을 지정할 수 있습니다. 

 

mat1 = zeros(Int8, (2, 3))
# 0으로 채워진 2행 3열의 배열을 생성합니다. 데이터타입으로 Int8을 지정하고 있습니다.

println(mat1)
# println 함수는 1차원 배열 형태로 출력합니다.
#
# Int8[0 0 0; 0 0 0]

display(mat1)
# display 함수는 시각적으로 배열 형태를 알아보기 쉽게 출력하며 배열 크기와 데이터 타입도 출력합니다.
# zeros함수로 배열을 생성시 옵션으로 데이터 타입을 지정할 수 있습니다. 여기에선 Int8로 지정합니다.
#
# 2×3 Matrix{Int8}:
#  0  0  0
#  0  0  0



배열 형태 변환 함수 - reshape

배열의 형태를 바꾸기 위해 reshape 함수를 사용합니다.

 

array1 = [i for i in 1:16]
# 인덱스 범위를 1에서 16까지하여 1차원 배열을 생성합니다.

println(array1)
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
display(array1)
# 16-element Vector{Int64}:
#   1
#   2
#   3
#   4
#   5
#   6
#   7
#   8
#   9
#  10
#  11
#  12
#  13
#  14
#  15
#  16


array2 = reshape([i for i in 1:16],4,4)
# 1차원 배열을 생성한 후, reshape 함수를 사용하여 4 x 4 배열로 변환합니다.

println(array2)
# [1 5 9 13; 2 6 10 14; 3 7 11 15; 4 8 12 16]
display(array2)
# 4×4 Matrix{Int64}:
#  1  5   9  13
#  2  6  10  14
#  3  7  11  15
#  4  8  12  16

mat1 = reshape([i for i in 1:16],4,4)
mat2 = mat1[2:3, 2:3]



좀더 간단한 reshape 함수 예제입니다.

 

a = [1,2,3,4,5,6,7,8,9]

println(a)
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
display(a)
# 1
# 2
# 3
# 4
# 5
# 6
# 7
# 8
# 9


println()


b = reshape([1,2,3,4,5,6,7,8,9],3,3)

println(b)
# [1 4 7; 2 5 8; 3 6 9]

display(b)
# 3×3 Matrix{Int64}:
#  1  4  7
#  2  5  8
#  3  6  9
#
# 1차원 배열이 3 x 3 크기의 2차원 배열로 변환됩니다.



N차원 배열(N-dimensional Arrays)



3차원 배열을 생성합니다. 

 

array1 = zeros(2,3,3)
array1[:,:,1] = [1 2 3; 4 5 6]
array1[:,:,2] = [7 8 9; 10 11 12]
array1[:,:,3] = [13 14 15; 16 17 18]



println(array1)
# [1.0 2.0 3.0; 4.0 5.0 6.0;;; 7.0 8.0 9.0; 10.0 11.0 12.0;;; 13.0 14.0 15.0; 16.0 17.0 18.0]
display(array1)
# 2 x 3 배열 3개로 구성된 2 x 3 x 3 배열을 생성합니다.
#
# 2×3×3 Array{Float64, 3}:
# [:, :, 1] =
#  1.0  2.0  3.0
#  4.0  5.0  6.0

# [:, :, 2] =
#   7.0   8.0   9.0
#  10.0  11.0  12.0

# [:, :, 3] =
#  13.0  14.0  15.0
#  16.0  17.0  18.0



3차원 배열을 다음처럼 생성할 수도 있습니다. 

 

three_dimensional = cat([1 2 3;4 5 6], [7 8 9;10 11 12], [13 14 15;16 17 18], dims=3)

println(three_dimensional)
# [1 2 3; 4 5 6;;; 7 8 9; 10 11 12;;; 13 14 15; 16 17 18]
display(three_dimensional)
# 2 x 3 배열 3개로 구성된 2 x 3 x 3 배열을 생성합니다.
#
# 2×3×3 Array{Int64, 3}:
# [:, :, 1] =
#  1  2  3
#  4  5  6

# [:, :, 2] =
#   7   8   9
#  10  11  12

# [:, :, 3] =
#  13  14  15
#  16  17  18




슬라이스(Slices)

배열의 일부에 접근하는 방법입니다. 



1차원 배열의 2번째 요소에서 5번째 요소까지 접근하려면 다음처럼 슬라이스를 사용하면 됩니다. 

 

a = [1,2,3,4,5,6]

println(a)
# [1, 2, 3, 4, 5, 6]
display(a)
# 6-element Vector{Int64}:
#  1
#  2
#  3
#  4
#  5
#  6

b = a[2:5]
# 배열 a의 두번째 요소부터 다섯번째 요소까지를 가져옵니다.
# 줄리아에선 인덱스가 1부터 시작하므로 두번째 요소의 인덱스는 2입니다.
# 인덱스 범위 지정시 마지막 요소가 포함됩니다.

println(b)
# [2, 3, 4, 5]
display(b)
# 인덱스 2에 있는 4부터 인덱스 5에 있는 5까지 그 사이에 있는 값을 가져옵니다.
#
# 4-element Vector{Int64}:
#  2
#  3
#  4
#  5




2차원 배열의 경우엔 행의 범위와 열의 범위를 각각 지정하여 슬라이스를 할 수 있습니다. 

 

mat1 = reshape([i for i in 1:16],4,4)
# 1~16 사이의 값으로 채워진 4 x 4 배열을 생성합니다.
# 자세한 설명은 reshape 함수가 설명된 부분을 참고하세요.

println(mat1)
# [1 5 9 13; 2 6 10 14; 3 7 11 15; 4 8 12 16]
display(mat1)
# 4×4 Matrix{Int64}:
#  1  5   9  13
#  2  6  10  14
#  3  7  11  15
#  4  8  12  16

mat2 = mat1[1:2, 2:3]
# 1행과 2행 그리고 2열과 3열로 범위가 지정되는 부분 배열을 슬라이싱합니다.

println(mat2)
# [5 9; 6 10]
display(mat2)
# 2×2 Matrix{Int64}:
#  5   9
#  6  10



뷰(Views)

다른 프로그래밍 언어처럼 배열은 메모리 내 위치를 가리키는 포인터이므로 배열을 다룰 때 주의해야 합니다. 



배열 a를 생성하고 b=a를 사용하여 a를 변수 b에 대입하면 변수 b를 사용하여 배열 a의 요소를 수정할 수 있습니다

 

a=[1,2,3]
# 배열 a를 생성합니다.

println(a)
# [1, 2, 3]
display(a)
# 3-element Vector{Int64}:
#  1
#  2
#  3

b=a
# 변수 b에 배열 a를 대입합니다.

# 변수 b도 배열 a와 똑같은 값을 가집니다.
println(b)
# [1, 2, 3]
display(b)
# 3-element Vector{Int64}:
#  1
#  2
#  3


b[2] = 42
# 변수 b를 사용하여 배열 a의 원소를 수정할 수 있습니다.


# 배열 a의 두번째 원소의 값이 2에서 42로 변경되었습니다.
println(a)
# [1, 42, 3]
display(a)
# 3-element Vector{Int64}:
#   1
#  42
#   3


# 물론 변수 b의 값도 배열 a의 값과 동일합니다.
println(b)
# [1, 42, 3]
display(b)
# 3-element Vector{Int64}:
#   1
#  42
#   3



Julia에서 변수에 다른 변수를 대입하면, 두 변수는 같은 데이터 객체를 가리키게 됩니다. 변수에 대입하는 것이 복사가 아닌 참조입니다. 예를 들어, b = a라는 할당이 있을 때, b와 a는 동일한 메모리 위치에 저장된 데이터를 가리킵니다. 따라서 a 또는 b 중 하나를 변경하면, 두 변수 모두에 변경이 반영됩니다.



view 함수는 배열의 부분집합에 대한 뷰(view)를 생성합니다. 이 뷰는 원본 배열의 특정 부분을 참조하지만, 원본 배열과 독립된 객체로 존재합니다.  원본 배열과 부분 배열에서 참조하는 영역은 접근하여 수정하면 양쪽에서도 똑같이 보입니다. 

 

a = [1, 2, 3, 4, 5]
v = view(a, 2:3)
# 변수 v는 변수 a에 저장되어 있는 배열의 일부 배열을 가리키는 뷰입니다.
println(a)
# [1, 2, 3, 4, 5]
println(v)
# [2, 3]


v[1] = 200
# 변수 v의 값을 변경하면 변수 a에 있는 값에도 영향을 주기 때문에 변수 a에 저장되어 있는 배열의 2번째 원소가 200으로 변경됩니다.

println(a)
# [1, 200, 3, 4, 5]
println(v)
# [200, 3]


a[2] = 1000
# 변수 a의 값을 변경하면 변수 v에 있는 값에도 영향을 주기 때문에 변수 v에 저장되어 있는 배열의 1번째 원소가 1000으로 변경됩니다.

println(a)
# [1, 1000, 3, 4, 5]
println(v)
# [1000, 3]



슬라이싱을 해도 view 함수를 사용한 것이랑 똑같이 동작합니다.

a = [1, 2, 3, 4, 5]
v = a[2:3]
# 슬라이싱을 하면 뷰와 동일하게 동작합니다.
println(a)
# [1, 2, 3, 4, 5]
println(v)
# [2, 3]


v[1] = 200
# 변수 v의 값을 변경하면 변수 a에 있는 값에도 영향을 주기 때문에 변수 a에 저장되어 있는 배열의 2번째 원소가 200으로 변경됩니다.

println(a)
# [1, 200, 3, 4, 5]
println(v)
# [200, 3]


a[2] = 1000
# 변수 a의 값을 변경하면 변수 v에 있는 값에도 영향을 주기 때문에 변수 v에 저장되어 있는 배열의 1번째 원소가 1000으로 변경됩니다.

println(a)
# [1, 1000, 3, 4, 5]
println(v)
# [1000, 3]




이 방법은 메모리를 절약할 수 있어 특히 유용하지만 원치 않는 결과를 초래할 수 있습니다. 배열의 복사본을 만들려면 copy 함수를 사용해야 합니다.

 

a = [1, 2, 3, 4, 5]
v = copy(a[2:3])
# copy 함수를 사용하면 참조하는게 아니라 해당 영역을 별도의 메모리에 저장합니다.
println(a)
# [1, 2, 3, 4, 5]
println(v)
# [2, 3]


v[1] = 200
# 변수 v의 값을 변경해도 변수 a에는 영향을 주지 않습니다.

# 변수 b의 첫번쨰 원소의 값만 바뀌었습니다.
println(a)
# [1, 2, 3, 4, 5]
println(v)
# [200, 3]


a[2] = 1000
# 변수 a의 값을 변경해도 변수 v에는 영향을 주지 않습니다.

# 변수 a의 두번째 원소의 값만 바뀌었습니다.
println(a)
# [1, 1000, 3, 4, 5]
println(v)
# [200, 3]



배열 안에 배열이 포함되어 있는 경우에는 copy함수를 사용하더라도 내부 배열은 참조하게 됩니다.

 

a = [[1, 2], [3, 4]]
v = copy(a[2:2])
# 다차원 배열의 경우 copy 함수를 사용하면 내부 배열은 참조합니다.
println(a)
# [[1, 2], [3, 4]]
println(v)
# [[3, 4]]


v[1][1] = 200
# 변수 v의 값을 변경하면 변수 a에 영향을 줍니다.

# 변수 a에 있는 배열의 값도 200으로 바뀌었습니다.
println(a)
# [[1, 2], [200, 4]]
println(v)
# [[200, 4]]


a[2][2] = 1000
# 변수 a의 값을 변경하면 변수 v에 영향을 줍니다.

# 변수 v에 있는 배열의 값도 1000으로 바뀌었습니다.
println(a)
# [[1, 2], [200, 1000]]
println(v)
# [[200, 1000]]



deepcopy 함수를 사용해야 내부 함수도 별도의 메모리에 저장합니다.

 

a = [[1, 2], [3, 4]]
v = deepcopy(a[2:2])
# 다차원 배열의 경우 deepcopy 함수를 사용해야 내부 배열도 별도의 메모리에 저장됩니다.
println(a)
# [[1, 2], [3, 4]]
println(v)
# [[3, 4]]


v[1][1] = 200
# 변수 v의 값을 변경해도 변수 a에 영향을 주지 않습니다.

# 변수 v에 있는 값만 200으로 바뀌었습니다.
println(a)
# [[1, 2], [3, 4]]
println(v)
# [[200, 4]]


a[2][2] = 1000
# 변수 a의 값을 변경해도 변수 v에 영향을 주지 않습니다.

# 변수 a에 있는 값만 1000으로 바뀌었습니다.
println(a)
# [[1, 2], [3, 1000]]
println(v)
# [[200, 4]]




튜플(Tuples)

튜플은 고정된 크기를 가지며 크기 변경이 불가능하며 여러가지 데이터 타입으로 구성할 수 있습니다.



다음처럼 괄호를 사용하거나 괄호 없이 튜플을 생성할 수 있습니다.

 

a = (1,2.0,"webnautes")
b = 1, 2.0, "webnautes"


println(a)
# (1, 2.0, "webnautes")
display(a)
# (1, 2.0, "webnautes")
println(typeof(a))
# Tuple{Int64, Float64, String}
#
# 각 원소의 데이터타입을 각각 출력해줍니다.

println(b)
# (1, 2.0, "webnautes")
#
# 괄호 없이 튜플을 생성해도 출력시 괄호가 추가됩니다.
display(b)
# (1, 2.0, "webnautes")
println(typeof(b))
# Tuple{Int64, Float64, String}




튜플로 저장되어 있는 값을 여러 변수에 각각 대입할 수 있습니다.

 

tuple1 = (1, 2, 3)
a, b, c = tuple1
# tuple1에 저장되어 있는 튜플의 값이 분리되어 각각 변수 a,b,c,에 저장됩니다.

print("$a $b $c")
# 1 2 3




함수의 리턴값으로 튜플을 사용할 수 있습니다. 함수의 리턴값을 받을 때 하나의 변수 또는 튜플의 원소개수 만큼 변수를 사용할 수 있습니다.

 

function return_multiple()
    return 42, 43, 44
end

# 함수의 튜플 리턴값을 개별 변수로 받습니다.
a, b, c = return_multiple()
println("$a $b $c")
# 42 43 44

# 함수의 튜플 리턴값을 하나의 변수로 받습니다.
all = return_multiple()
println(all)
# (42, 43, 44)




Splatting

다음처럼 튜플을 함수의 아규먼트로 전달할 수 있습니다.

 

function splat_me(a, b, c)
    return a*b*c
end

tuple1 = (1,2,3)

ret = splat_me(tuple1...)
# 튜플이 저장된 변수 다음에 ...을 추가하여 튜플이 분리되어 아규먼트로 전달되어야 함을 알려줍니다.

print(ret)
# 6



네임드 튜플(Named tuples)

네임드 튜플은 튜플과 비슷합니다. 차이가 있다면 개별 값에 식별자가 있습니다.

 

namedTuple1 = (a = 1, b = "hello")

println(namedTuple1)
# (a = 1, b = "hello")


# 이름을 지정하여 네임드 튜플의 원소를 출력할 수 있습니다.
println(namedTuple1[:a])
# 1
println(namedTuple1[:b])
# hello




네임드 튜플을 다음처럼 생성할 수도 있습니다.

 

namedTuple1 = NamedTuple{(:a, :b)}((1, "hello"))
println(namedTuple1)
# (a = 1, b = "hello")


# 이름을 지정하여 네임드 튜플의 원소를 출력할 수 있습니다.
println(namedTuple1[:a])
# 1
println(namedTuple1[:b])
# hello



딕셔너리(Dictionaries)

딕셔너리는 키와 값의 모음입니다.  비어 있는 딕셔너리를 생성한 후, 요소를 추가/ 삭제하는 예제 코드입니다. 이 경우엔 딕셔너리의 키와 값에 대한 데이터타입이 결정되지 않고 Any가 되어 어떤 데이터든 저장할 수 있는 상태가 됩니다.

 

# 딕셔너리 생성
fruits = Dict()

# 딕셔너리에 요소 추가
fruits["orange"] = "orange"
fruits["apple"] = "red"
fruits["banana"] = "yellow"

# 특정 키의 값을 출력
println(fruits["apple"])
# red

# 딕셔너리 전체 출력
println(fruits)
# Dict{Any, Any}("orange" => "orange", "banana" => "yellow", "apple" => "red")

# 딕셔너리에서 요소 제거
pop!(fruits, "banana")

# 수정된 딕셔너리 출력
println(fruits)
# Dict{Any, Any}("orange" => "orange", "apple" => "red")

# 딕셔너리에 있는 모든 키와 값 순회
for (fruit, color) in fruits
    println("The color of a $fruit is $color")
end
# The color of a orange is orange
# The color of a apple is red




딕셔너리 생성시 요소를 추가할 수도 있습니다.  이 경우에는 딕셔너리의 키와 값의 데이터타입이 String으로 유츄됩니다.

 

# 딕셔너리 생성
fruits = Dict("apple" => "red", "banana" => "yellow")


# 딕셔너리 전체 출력
println(fruits)
# Dict("banana" => "yellow", "apple" => "red")

println(typeof(fruits))
# Dict{String, String}



딕셔너리의 키와 값의 데이터 타입을 지정할 수 있습니다.

 

# 문자열 키와 문자열 값을 갖는 빈 딕셔너리 생성
fruits = Dict{String, Int32}()

# 딕셔너리에 요소 추가
fruits["orange"] = 1
fruits["apple"] = 2
fruits["banana"] = 3

# 딕셔너리 전체 출력
println(fruits)
# Dict{String, Int32}("orange" => 1, "banana" => 3, "apple" => 2)

println(typeof(fruits))
# Dict{String, Int32}

 

반응형

문제 발생시 지나치지 마시고 댓글 남겨주시면 가능한 빨리 답장드립니다.

도움이 되셨다면 토스아이디로 후원해주세요.
https://toss.me/momo2024


제가 쓴 책도 한번 검토해보세요 ^^

+ Recent posts