티스토리 뷰

3_Data_structures

Data structures

Reference

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

Topics:

  1. Tuples
  2. Dictionaries
  3. Arrays
  4. Exercises

Series

Tuples

We can create a tuple by enclosing an ordered collection of enements in ( ).

Syntax:

(item1, item2, ...)
In [1]:
myfavoriteanimals = ("penguins","cats","sugargliders")
Out[1]:
("penguins", "cats", "sugargliders")

We can index into this tuple.

In [2]:
myfavoriteanimals[1]
Out[2]:
"penguins"

but since tuples are immutable, we can't update it

In [3]:
myfavoriteanimals[1] = "otters"
MethodError: no method matching setindex!(::Tuple{String,String,String}, ::String, ::Int64)

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

NamedTuples

As you might guess, NamedTuples are just like Tuples except that each element additionally have a name! They have a special syntax using = inside a tuple:

(name1 = item1, name2 = item2, ...)
In [4]:
myfavoriteanimals = (bird = "penguins", mammal = "cats", marsupial = "sugargliders")
Out[4]:
(bird = "penguins", mammal = "cats", marsupial = "sugargliders")

Like regular Tuples, NamedTuples are ordered, so we can retrieve their elements via indexing:

In [5]:
myfavoriteanimals[1]
Out[5]:
"penguins"

They also add the special ability to access values by their name:

In [6]:
myfavoriteanimals.bird
Out[6]:
"penguins"

The code below does not work.

In [7]:
myfavoriteanimals["bird"]
MethodError: no method matching getindex(::NamedTuple{(:bird, :mammal, :marsupial),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

This works:

In [8]:
myfavoriteanimals[:bird]
Out[8]:
"penguins"

Dictionaries

If we have sets of data related to one another, we may choose to store that data in a dictionary. We can create a dictionary using the Dict() function, which we can initialize as an empty dictionary or one storing key, value pairs.

Syntax:

Dict(key1 => value1, key2 => value2, ...)
In [9]:
myphonebook = Dict("Jenny" => "867-5309", "Ghostbusters" => "555-2368")
Out[9]:
Dict{String,String} with 2 entries:
  "Jenny"        => "867-5309"
  "Ghostbusters" => "555-2368"

In this example, each name and number is a "key" and "value" pair. We can grab Jenny's number (a value) using the associated key

In [10]:
myphonebook["Jenny"]
Out[10]:
"867-5309"

We can add another entry to this dictionary as follows

In [11]:
myphonebook["Kramer"] = "555-FILK"
Out[11]:
"555-FILK"
In [12]:
myphonebook
Out[12]:
Dict{String,String} with 3 entries:
  "Jenny"        => "867-5309"
  "Kramer"       => "555-FILK"
  "Ghostbusters" => "555-2368"

We can delete Kramer from our contact list - and simultaneously grab his number - by using pop!

In [13]:
pop!(myphonebook, "Kramer")
Out[13]:
"555-FILK"
In [14]:
myphonebook
Out[14]:
Dict{String,String} with 2 entries:
  "Jenny"        => "867-5309"
  "Ghostbusters" => "555-2368"

Unlike tuples and arrays, dictionaries are not ordered. So, we can't index into them.

In [15]:
myphonebook[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

In the example above, julia thinks you're trying to access a value associated with the key 1.

The code below does not work.

In [16]:
myphonebook.Jenny
type Dict has no field Jenny

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

Arrays

Unlike tuples, arrays are mutable. Unlike dictionaries, arrays contain ordered collections. We can create an array by enclosing this collection in [ ].

Syntax:

[item1, item2, ...]

For example, we might create an array to keep track of my friends

In [17]:
myfriends = ["Ted", "Robyn", "Barney", "Lily", "Marshall"]
Out[17]:
5-element Array{String,1}:
 "Ted"     
 "Robyn"   
 "Barney"  
 "Lily"    
 "Marshall"

The 1 in Array{String,1} means this is a one dimensional vector. An Array{String,2} would be a 2d matrix, etc. The String is the type of each element.

or to store a sequence of numbers

In [18]:
fibonacci = [1, 1, 2, 3, 5, 8, 13]
Out[18]:
7-element Array{Int64,1}:
  1
  1
  2
  3
  5
  8
 13
In [19]:
mixture = [1, 1, 2, 3, "Ted", "Robyn"]
Out[19]:
6-element Array{Any,1}:
 1       
 1       
 2       
 3       
  "Ted"  
  "Robyn"

Once we have an array, we can grab individual pieces of data from inside that array by indexing into the array. For example, if we want the third friend listed in myfriends, we write

In [20]:
myfriends[3]
Out[20]:
"Barney"

We can use indexing to edit an existing element of an array

In [21]:
myfriends[3] = "Baby Bop"
Out[21]:
"Baby Bop"
In [22]:
myfriends
Out[22]:
5-element Array{String,1}:
 "Ted"     
 "Robyn"   
 "Baby Bop"
 "Lily"    
 "Marshall"

Yes, Julia is 1-based indexing, not 0-based like Python. Wars are faught over lesser issues. I have a friend with the wisdom of Solomon who proposes settling this once and for all with ½ 😃

We can also edit the array by using the push! and pop! functions. push! adds an element to the end of an array and pop! removes the last element of an array.

We can add another number to our fibonnaci sequence

In [23]:
push!(fibonacci, 21)
Out[23]:
8-element Array{Int64,1}:
  1
  1
  2
  3
  5
  8
 13
 21
In [24]:
fibonacci
Out[24]:
8-element Array{Int64,1}:
  1
  1
  2
  3
  5
  8
 13
 21

and then remove it

In [25]:
pop!(fibonacci)
Out[25]:
21
In [26]:
fibonacci
Out[26]:
7-element Array{Int64,1}:
  1
  1
  2
  3
  5
  8
 13

So far I've given examples of only 1D arrays of scalars, but arrays can have an arbitrary number of dimensions and can also store other arrays.

For example, the following are arrays of arrays:

In [27]:
favorites = [["koobideh", "chocolate", "eggs"],["penguins", "cats", "sugargliders"]]
Out[27]:
2-element Array{Array{String,1},1}:
 ["koobideh", "chocolate", "eggs"]   
 ["penguins", "cats", "sugargliders"]
In [28]:
numbers = [[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]

Below is an example of 2D array.

In [29]:
favorites2D = [["koobideh", "chocolate", "eggs"] ["penguins", "cats", "sugargliders"]]
Out[29]:
3×2 Array{String,2}:
 "koobideh"   "penguins"    
 "chocolate"  "cats"        
 "eggs"       "sugargliders"

Below are examples of 2D and 3D arrays populated with random values.

In [30]:
rand(4, 3)
Out[30]:
4×3 Array{Float64,2}:
 0.0468554  0.470043   0.8623  
 0.110495   0.850854   0.150581
 0.69142    0.0290748  0.951877
 0.28233    0.0542284  0.124464
In [31]:
rand(4, 3, 2)
Out[31]:
4×3×2 Array{Float64,3}:
[:, :, 1] =
 0.284478  0.451184   0.401792
 0.666625  0.978789   0.910275
 0.14843   0.0796421  0.736579
 0.653282  0.8088     0.24662 

[:, :, 2] =
 0.837548   0.321428  0.3206  
 0.161516   0.794511  0.537481
 0.107384   0.444637  0.168577
 0.0167821  0.783351  0.718907

Be careful when you want to copy arrays!

In [32]:
fibonacci
Out[32]:
7-element Array{Int64,1}:
  1
  1
  2
  3
  5
  8
 13
In [33]:
somenumbers = fibonacci
Out[33]:
7-element Array{Int64,1}:
  1
  1
  2
  3
  5
  8
 13
In [34]:
somenumbers[1] = 404
Out[34]:
404
In [35]:
fibonacci
Out[35]:
7-element Array{Int64,1}:
 404
   1
   2
   3
   5
   8
  13

Editing somenumbers caused fibonacci to get updated as well!

In the above example, we didn't actually make a copy of fibonacci. We just created a new way to access the entries in the array bound to fibonacci.

If we'd like to make a copy of the array bound to fibonacci, we can use the copy function.

first, restore fibonacci.

In [36]:
fibonacci[1] = 1
fibonacci
Out[36]:
7-element Array{Int64,1}:
  1
  1
  2
  3
  5
  8
 13
In [37]:
somemorenumbers = copy(fibonacci)
Out[37]:
7-element Array{Int64,1}:
  1
  1
  2
  3
  5
  8
 13
In [38]:
somemorenumbers[1] = 404
Out[38]:
404
In [39]:
fibonacci
Out[39]:
7-element Array{Int64,1}:
  1
  1
  2
  3
  5
  8
 13

In this last example, fibonacci was not updated. Therefore we see that the arrays bound to somemorenumbers and fibonacci are distinct.

Exercises

3.1

Create an array, a_ray, with the following code:

a_ray = [1, 2, 3]

Add the number 4 to the end of this array and then remove it.

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

Try to add "Emergency" as key to myphonebook with the value string(911) with the following code

myphonebook["Emergency"] = 911

Why doesn't this work?

In [46]:
myphonebook
Out[46]:
Dict{String,String} with 2 entries:
  "Jenny"        => "867-5309"
  "Ghostbusters" => "555-2368"
In [47]:
myphonebook["Emergency"] = 911
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]:
myphonebook["Emergency"] = string(911)
Out[48]:
"911"

3.3

Create a new dictionary called flexible_phonebook that has Jenny's number stored as an integer and Ghostbusters' number stored as a string with the following code

flexible_phonebook = Dict("Jenny" => 8675309, "Ghostbusters" => "555-2368")
In [49]:
flexible_phonebook = Dict("Jenny" => 8675309, "Ghostbusters" => "555-2368")
Out[49]:
Dict{String,Any} with 2 entries:
  "Jenny"        => 8675309
  "Ghostbusters" => "555-2368"
In [50]:
@assert flexible_phonebook == Dict("Jenny" => 8675309, "Ghostbusters" => "555-2368")

3.4

Why can we add an integer as a value to flexible_phonebook but not myphonebook? How could we have initialized myphonebook so that it would accept integers as values?

In [51]:
flexible_phonebook["Emergency"] = 911
Out[51]:
911
In [52]:
flexible_phonebook
Out[52]:
Dict{String,Any} with 3 entries:
  "Jenny"        => 8675309
  "Emergency"    => 911
  "Ghostbusters" => "555-2368"
In [53]:
typeof(flexible_phonebook)
Out[53]:
Dict{String,Any}
In [54]:
typeof(myphonebook)
Out[54]:
Dict{String,String}
In [64]:
myphonebook = convert(Dict{Any,Any},myphonebook)
Out[64]:
Dict{Any,Any} with 3 entries:
  "Jenny"        => "867-5309"
  "Emergency"    => "911"
  "Ghostbusters" => "555-2368"
In [65]:
typeof(myphonebook)
Out[65]:
Dict{Any,Any}
In [66]:
myphonebook["Emergency"] = 911
Out[66]:
911
In [67]:
myphonebook
Out[67]:
Dict{Any,Any} with 3 entries:
  "Jenny"        => "867-5309"
  "Emergency"    => 911
  "Ghostbusters" => "555-2368"

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

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
01. Getting started (한글)  (0) 2018.09.11
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/05   »
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
글 보관함