티스토리 뷰

3_Data_structures(한글)

Data structures

출처

https://github.com/JuliaComputing/JuliaBoxTutorials/tree/master/intro-to-julia (github : JuliaComputing/JuliaBoxTutorials/intro-to-julia)

Topics:

  1. Tuples
  2. Dictionaries
  3. Arrays
  4. 연습문제

함께보기

Tuples

구성요소를 순서대로 적고 ( ) 로 감싸서 tuple 을 만들 수 있다.

구문:

(값1, 값2, ...)
In [1]:
좋아하는동물 = ("펭귄","고양이","다람쥐")
Out[1]:
("펭귄", "고양이", "다람쥐")

index를 이용해서 값을 가져올 수 있다.

In [2]:
좋아하는동물[1]
Out[2]:
"펭귄"

그러나 튜플은 변경 불가능 하기 때문에 업데이트가 안 된다.

In [3]:
좋아하는동물[1] = "수달"
MethodError: no method matching setindex!(::Tuple{String,String,String}, ::String, ::Int64)

Stacktrace:
 [1] top-level scope at In[3]:1

NamedTuples

이름을 보고 생각한 것 처럼, NamedTuple은 구성요소에 이름이 있다는 점을 제외하면 Tuple이다. NamedTuple은 Tuple안에 =를 이용하는 구문을 가진다:

(이름1 = 값1, 이름2 = 값2, ...)
In [4]:
좋아하는동물 = (조류 = "펭귄", 포유류 = "고양이", 유대류 = "다람쥐")
Out[4]:
(조류 = "펭귄", 포유류 = "고양이", 유대류 = "다람쥐")

보통의 Tuple 처럼, NamedTuple은 순서가 있어서 index를 이용해서 값을 가져올 수 있다:

In [5]:
좋아하는동물[1]
Out[5]:
"펭귄"

또한 이름을 이용해서 값을 불러올 수도 있다:

In [6]:
좋아하는동물.조류
Out[6]:
"펭귄"

아래처럼 쓰면 오류난다.

In [7]:
좋아하는동물["조류"]
MethodError: no method matching getindex(::NamedTuple{(:조류, :포유류, :유대류),Tuple{String,String,String}}, ::String)
Closest candidates are:
  getindex(::NamedTuple, !Matched::Int64) at namedtuple.jl:101
  getindex(::NamedTuple, !Matched::Symbol) at namedtuple.jl:102

Stacktrace:
 [1] top-level scope at In[7]:1

이거는 된다.

In [8]:
좋아하는동물[:조류]
Out[8]:
"펭귄"

Dictionaries

어떤 데이터가 서로서로 관련되어 있을 때, Dictionary를 써서 자료를 저장할 수도 있다. Dict() 를 써서 dictionary를 만들 수 있는데, 초기화 하려면 빈 dictionary를 만들거나 1개의 key, value 쌍을 이용하면 된다.

구문:

Dict(key1 => value1, key2 => value2, ...)
In [9]:
연락처 = Dict("영희" => "867-5309", "퇴마사" => "555-2368")
Out[9]:
Dict{String,String} with 2 entries:
  "퇴마…  => "555-2368"
  "영희…  => "867-5309"

이 예시에서, 이름과 번호는 각각 key와 value 쌍이다. 영희의 전화번호를 끄집어 낼 때, 연관된 key를 이용하면 된다.

In [10]:
연락처["영희"]
Out[10]:
"867-5309"

아래와 같이 하면 이 dictionary에 다른 값도 추가할 수 있다.

In [11]:
연락처["철수"] = "555-달려"
Out[11]:
"555-달려"
In [12]:
연락처
Out[12]:
Dict{String,String} with 3 entries:
  "퇴마…  => "555-2368"
  "영희…  => "867-5309"
  "철수…  => "555-달려"

pop! 을 이용해서 철수의 번호를 끄집어내면서 동시에 연락처에서 지울 수 있다.

In [13]:
pop!(연락처, "철수")
Out[13]:
"555-달려"
In [14]:
연락처
Out[14]:
Dict{String,String} with 2 entries:
  "퇴마…  => "555-2368"
  "영희…  => "867-5309"

Tuple과 Array와는 다르게, dictionary는 순서가 없다. 그래서 index를 이용할 수 없다.

In [15]:
연락처[1]
KeyError: key 1 not found

Stacktrace:
 [1] getindex(::Dict{String,String}, ::Int64) at ./dict.jl:478
 [2] top-level scope at In[15]:1

위의 예시처럼, julia는 key 1과 연관된 값을 불러오려고 하는지 아닌지 판단할 수 없다.

참고로, 아래처럼 쓰면 오류난다.

In [16]:
연락처.영희
type Dict has no field 영희

Stacktrace:
 [1] getproperty(::Any, ::Symbol) at ./sysimg.jl:18
 [2] top-level scope at In[16]:1

Arrays

Tuple과는 다르게, Array는 변할 수 있다. Dictionary와는 다르게, Array는 순서가 있다. Array를 만드려면, [ ] 로 값을 감싸면 된다.

구문:

[값1, 값2, ...]

예를 들어, 친구 목록을 만들 수 있다.

In [17]:
친구목록 = ["균우", "상완", "동훈", "진", "재현"]
Out[17]:
5-element Array{String,1}:
 "균우"
 "상완"
 "동훈"
 "진" 
 "재현"

Array{String,1}에서 1이 의미하는 바는, 만들어진 Array가 1차원 벡터라는 것이다. Array{String,2}는 2차원 행렬, Array{String,3}은 3차원 tensor 같은 식이다. String은 값들의 형식이다.

Array에 수열을 저장할 수도 있다.

In [18]:
피보나치 = [1, 1, 2, 3, 5, 8, 13]
Out[18]:
7-element Array{Int64,1}:
  1
  1
  2
  3
  5
  8
 13
In [19]:
섞인거 = [1, 1, 2, 3, "Ted", "Robyn"]
Out[19]:
6-element Array{Any,1}:
 1       
 1       
 2       
 3       
  "Ted"  
  "Robyn"

Array는 Index를 이용해서 일부 값을 불러낼 수 있다.

In [20]:
친구목록[3]
Out[20]:
"동훈"

Index를 이용해서 값을 덮어쓸 수도 있다.

In [21]:
친구목록[3] = "아기 새"
Out[21]:
"아기 새"
In [22]:
친구목록
Out[22]:
5-element Array{String,1}:
 "균우"  
 "상완"  
 "아기 새"
 "진"   
 "재현"  

Python의 Index는 0부터 시작하지만, Julia의 Index는 1부터 시작한다. (뒷 문장의 영어 해석은 0에서 시작할지 1에서 시작할지 의견이 분분하다느니의 얘기인데, 개발자의 고충을 알아달라는 것 같다.)

push!pop!을 이용해서 수정할 수 있다. push!를 이용하면 마지막 값을 추가할 수 있고, pop!을 이용하면 마지막 값을 제거할 수 있다.

예를 들면, 피보나치에 값을 하나 더 추가하거나 제거할 수 있다.

In [23]:
push!(피보나치, 21)
Out[23]:
8-element Array{Int64,1}:
  1
  1
  2
  3
  5
  8
 13
 21
In [24]:
피보나치
Out[24]:
8-element Array{Int64,1}:
  1
  1
  2
  3
  5
  8
 13
 21
In [25]:
pop!(피보나치)
Out[25]:
21
In [26]:
피보나치
Out[26]:
7-element Array{Int64,1}:
  1
  1
  2
  3
  5
  8
 13

이때까지 scalar값의 1D array 만 고려했지만, Array는 모든 차원을 가질 수 있고, 다른 Array 또한 포함 할 수 있다.

예를 들어, 아래는 Array를 포함하는 Array이다.

In [27]:
좋아하는것 = [["꼬치", "초콜릿", "계란"],["폥귄", "고양이", "다람쥐"]]
Out[27]:
2-element Array{Array{String,1},1}:
 ["꼬치", "초콜릿", "계란"] 
 ["폥귄", "고양이", "다람쥐"]
In [28]:
숫자 = [[1, 2, 3], [4, 5], [6, 7, 8, 9]]
Out[28]:
3-element Array{Array{Int64,1},1}:
 [1, 2, 3]   
 [4, 5]      
 [6, 7, 8, 9]

아래는 2D Array의 예이다.

In [29]:
좋아하는것 = [["꼬치", "초콜릿", "계란"] ["폥귄", "고양이", "다람쥐"]]
Out[29]:
3×2 Array{String,2}:
 "꼬치"   "폥귄" 
 "초콜릿"  "고양이"
 "계란"   "다람쥐"

아래는 난수로 이루어진 2D 와 3D Array 의 예다.

In [30]:
rand(4, 3)
Out[30]:
4×3 Array{Float64,2}:
 0.155066  0.895017  0.344896 
 0.961225  0.250571  0.0275144
 0.962236  0.517302  0.512453 
 0.670154  0.910416  0.461275 
In [31]:
rand(4, 3, 2)
Out[31]:
4×3×2 Array{Float64,3}:
[:, :, 1] =
 0.473565  0.952828  0.992356  
 0.215875  0.68861   0.571616  
 0.93695   0.857364  0.00280746
 0.250034  0.613547  0.971052  

[:, :, 2] =
 0.186974  0.0946618  0.290266
 0.513068  0.632347   0.437898
 0.378373  0.817551   0.444273
 0.356178  0.053548   0.313712

Array를 복사할 때는 항상 주의해야한다!

In [32]:
피보나치
Out[32]:
7-element Array{Int64,1}:
  1
  1
  2
  3
  5
  8
 13
In [33]:
수열 = 피보나치
Out[33]:
7-element Array{Int64,1}:
  1
  1
  2
  3
  5
  8
 13
In [34]:
수열[1] = 404
Out[34]:
404
In [35]:
피보나치
Out[35]:
7-element Array{Int64,1}:
 404
   1
   2
   3
   5
   8
  13

수열을 수정했는데 피보나치도 수정됐다!

위의 예시에서 수열은 사실 피보나치의 복사본이 아니다. 그저 피보나치의 별칭을 만들어줬을 뿐이다.

피보나치의 복사본을 만들고 싶을 때는, copy 함수를 사용한다.

일단, 피보나치를 복구하자.

In [36]:
피보나치[1] = 1
피보나치
Out[36]:
7-element Array{Int64,1}:
  1
  1
  2
  3
  5
  8
 13
In [37]:
수열 = copy(피보나치)
Out[37]:
7-element Array{Int64,1}:
  1
  1
  2
  3
  5
  8
 13
In [38]:
수열[1] = 404
Out[38]:
404
In [39]:
피보나치
Out[39]:
7-element Array{Int64,1}:
  1
  1
  2
  3
  5
  8
 13

마지막 결과에서, 피보나치는 수정되지 않았다. 수열피보나치가 전혀 별개의 변수가 되었음을 볼 수 있다.

연습문제

3.1

아래 코드를 사용해서 a_ray라는 Array를 만들자:

a_ray = [1, 2, 3]

4를 추가했다가 삭제해보자.

In [40]:
a_ray = [1, 2, 3]
Out[40]:
3-element Array{Int64,1}:
 1
 2
 3
In [41]:
push!(a_ray,4)
Out[41]:
4-element Array{Int64,1}:
 1
 2
 3
 4
In [42]:
pop!(a_ray)
Out[42]:
4
In [43]:
a_ray
Out[43]:
3-element Array{Int64,1}:
 1
 2
 3
In [44]:
@assert a_ray == [1, 2, 3]
In [45]:
?@assert
Out[45]:
@assert cond [text]

Throw an AssertionError if cond is false. Preferred syntax for writing assertions. Message text is optionally displayed upon assertion failure.

!!! warning An assert might be disabled at various optimization levels. Assert should therefore only be used as a debugging tool and not used for authentication verification (e.g., verifying passwords), nor should side effects needed for the function to work correctly be used inside of asserts.

Examples

jldoctest
julia> @assert iseven(3) "3 is an odd number!"
ERROR: AssertionError: 3 is an odd number!

julia> @assert isodd(3) "What even are numbers?"

3.2

아래 코드를 이용해서 연락처에 "응급시" 라는 key와 string(119) 이라는 value를 추가하자.

연락처["응급시"] = 119

왜 오류가 날까?

In [46]:
연락처
Out[46]:
Dict{String,String} with 2 entries:
  "퇴마…  => "555-2368"
  "영희…  => "867-5309"
In [47]:
연락처["응급시"] = 119
MethodError: Cannot `convert` an object of type Int64 to an object of type String
Closest candidates are:
  convert(::Type{T<:AbstractString}, !Matched::T<:AbstractString) where T<:AbstractString at strings/basic.jl:207
  convert(::Type{T<:AbstractString}, !Matched::AbstractString) where T<:AbstractString at strings/basic.jl:208
  convert(::Type{T}, !Matched::T) where T at essentials.jl:154

Stacktrace:
 [1] setindex!(::Dict{String,String}, ::Int64, ::String) at ./dict.jl:381
 [2] top-level scope at In[47]:1
In [48]:
연락처["응급시"] = string(119)
Out[48]:
"119"

3.3

아래 코드를 이용해서 유연한연락처라는 새로운 Dictionary를 만들자. 영희 전화번호는 정수로 저장하고 퇴마사 전화번호는 문자로 저장한다.

유연한연락처 = Dict("영희" => 8675309, "퇴마사" => "555-2368")
In [49]:
유연한연락처 = Dict("영희" => 8675309, "퇴마사" => "555-2368")
Out[49]:
Dict{String,Any} with 2 entries:
  "퇴마…  => "555-2368"
  "영희…  => 8675309
In [50]:
@assert 유연한연락처 == Dict("영희" => 8675309, "퇴마사" => "555-2368")

3.4

어떤 정수 값을 유연한연락처에는 넣을 수 있는데, 왜 연락처에는 못 넣을까? 그럼, 연락처를 어떻게 선언해야 정수값을 넣을 수 있게 될까?

In [51]:
유연한연락처["응급시"] = 911
Out[51]:
911
In [52]:
유연한연락처
Out[52]:
Dict{String,Any} with 3 entries:
  "퇴마…  => "555-2368"
  "영희…  => 8675309
  "응급…  => 911
In [53]:
typeof(유연한연락처)
Out[53]:
Dict{String,Any}
In [54]:
typeof(연락처)
Out[54]:
Dict{String,String}
In [55]:
연락처 = convert(Dict{Any,Any},연락처)
Out[55]:
Dict{Any,Any} with 3 entries:
  "퇴마…  => "555-2368"
  "영희…  => "867-5309"
  "응급…  => "119"
In [56]:
typeof(연락처)
Out[56]:
Dict{Any,Any}
In [57]:
연락처["응급시"] = 119
Out[57]:
119
In [58]:
연락처
Out[58]:
Dict{Any,Any} with 3 entries:
  "퇴마…  => "555-2368"
  "영희…  => "867-5309"
  "응급…  => 119

'Flux in Julia > Learning Julia (Intro_to_Julia)' 카테고리의 다른 글

04. Loops (한글)  (0) 2018.09.15
04. Loops  (0) 2018.09.15
03. Data structures  (0) 2018.09.13
02. Strings (한글)  (0) 2018.09.12
02. Strings  (0) 2018.09.12
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/07   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함