How to iterate over Dict in Julia - dictionary

How can I something like this (it is in Python) in Julia?
for key, value in dictionary.items(): # <-- I don't know how to iterate over keys and values of a dictionary in Julia
print(key, value)
Thank you.

You can just iterate, but you need a bracket around (key, value):
julia> dict = Dict(i => (i/10 + rand(1:99)) for i = 1:3)
Dict{Int64, Float64} with 3 entries:
2 => 24.2
3 => 29.3
1 => 41.1
julia> for (k,v) in dict
#show k v
end
k = 2
v = 24.2
k = 3
v = 29.3
k = 1
v = 41.1
julia> p = first(dict)
2 => 24.2
julia> typeof(p)
Pair{Int64, Float64}
julia> (a, b) = p;
julia> b
24.2

Related

How can I not change the matrix

In Julia, if t is some matrix
t = [1 2; 3 4]
t1 = t
t1[1,1] = 0
t2 = t
t2 gives out same output as t1.
How can I make t2 to equal t?
They are all equal actually:
julia> t = [1 2; 3 4]
2×2 Matrix{Int64}:
1 2
3 4
julia> t1 = t
2×2 Matrix{Int64}:
1 2
3 4
julia> t1[1,1] = 0
0
julia> t2 = t
2×2 Matrix{Int64}:
0 2
3 4
julia> t == t1 == t2
true
julia> t === t1 === t2
true
julia> pointer(t), pointer(t1), pointer(t2) # identical
(Ptr{Int64} #0x00007fd213d37000, Ptr{Int64} #0x00007fd213d37000, Ptr{Int64} #0x00007fd213d37000)
The variables t, t1, and t2 point to the same data, the same memory location. So when you mutate t1 you mutate all.
If you want them to be different, such that only one is modified, you have to use copy:
julia> t = [1 2; 3 4];
julia> t1 = copy(t);
julia> t1[1,1] = 0;
julia> t2 = copy(t); # or just t if you want to avoid the copy
julia> t == t1 == t2
false
julia> pointer(t), pointer(t1), pointer(t2)
(Ptr{Int64} #0x00007fd21220e900, Ptr{Int64} #0x00007fd2142f9630, Ptr{Int64} #0x00007fd2142f9a90)

How to select odd numbers from a matrix?

How do you select odd numbers from a matrix larger than 29?
You can use filter:
filter(x->isodd(x)&&x>29, M)
Here, x->isodd(x)&&x>29 is an anonymous function, specifying your filter criterium, and M is your matrix.
Example:
julia> M = rand(1:50, 3,3)
3×3 Array{Int64,2}:
20 42 35
23 6 31
28 4 4
julia> filter(x->isodd(x)&&x>29, M)
2-element Array{Int64,1}:
35
31
Alternatively, you can use array comprehensions:
julia> [x for x in M if isodd(x) && x>29]
2-element Array{Int64,1}:
35
31
You can also use this:
using Statistics;
A = round.(rand(5,5)*10)
odd = A[(rem.(A,2).>0) .& (A.>29)]

newline sensitive interpretation of Arrays

When I add a newline to my array definition, the type of my array changes.
julia> a = [[1]]
1-element Array{Array{Int64,1},1}:
[1]
julia> a = [[1]
]
1-element Array{Int64,1}:
1
I thought they both should return the same result i.e. of type Array{Array{Int64,1},1}
In order to understand this see the following:
julia> :([[1]
])
:([[1];])
And you see that adding a newline is rewritten as vcat operation.
The reason for this is to allow writing something like this:
julia> x = [1 2
3 4]
2×2 Array{Int64,2}:
1 2
3 4
and your example is hitting a corner case of this syntax.
Note, however, that without an extra empty line vcat is not called:
julia> :([[1]
])
:([[1]])
Another use-case that is worth to know is:
julia> [[1, 2]
[3, 4]]
4-element Array{Int64,1}:
1
2
3
4
and the same with variables (can improve code readability in some cases):
julia> a = [1,2]
2-element Array{Int64,1}:
1
2
julia> b = [3, 4]
2-element Array{Int64,1}:
3
4
julia> [a
b]
4-element Array{Int64,1}:
1
2
3
4

Find the tail of array except first element

Is there a method to get the tail of a collection(e.g. vector) i.e. the array except the first element. Currently, I have
tail(arr) = selectdim(arr, 1, 2:length(arr))
julia> c
3-element Array{Int64,1}:
1
2
3
julia> tail(c)
2-element view(::Array{Int64,1}, 2:3) with eltype Int64:
2
3
Simply use the end keyword:
julia> c = [11,12,13]
3-element Array{Int64,1}:
11
12
13
julia> c[2:end]
2-element Array{Int64,1}:
12
13

Create a sparse symmetric random matrix in Julia

is there an easy way to create a sparse symmetric random matrix in Julia?
Julia has the command
sprand(m,n,d)
which "Creates a [sparse] m-by-n random matrix (of density d) with iid non-zero elements distributed uniformly on the half-open interval [0,1)[0,1)." But as far as I can tell this doesn't necessarily return a symmetric matrix.
I am looking for an equivalent command to MATLAB's
R = sprandsym(n,density)
which automatically creates a sparse symmetric random matrix. If such a command isn't implemented yet, what would be a workaround to transform the matrix returned by sprand(m,n,d) into a symmetric one?
Thank you!
You could Symmetric(sprand(10,10,0.4))
To avoid extra memory caveat mentioned in the comment to Michael Borregaard's answer, the following function takes a sparse matrix and drops the entries in the lower triangular part. If the SparseMatrixCSC format is unfamiliar, it also serves as a good presentation of how the format is manipulated:
function droplower(A::SparseMatrixCSC)
m,n = size(A)
rows = rowvals(A)
vals = nonzeros(A)
V = Vector{eltype(A)}()
I = Vector{Int}()
J = Vector{Int}()
for i=1:n
for j in nzrange(A,i)
rows[j]>i && break
push!(I,rows[j])
push!(J,i)
push!(V,vals[j])
end
end
return sparse(I,J,V,m,n)
end
Example usage:
julia> a = [0.5 1.0 0.0 ; 2.0 0.0 0.0 ; 0.0 0.0 0.0]
3×3 Array{Float64,2}:
0.5 1.0 0.0
2.0 0.0 0.0
0.0 0.0 0.0
julia> b = sparse(a)
3×3 SparseMatrixCSC{Float64,Int64} with 3 stored entries:
[1, 1] = 0.5
[2, 1] = 2.0
[1, 2] = 1.0
julia> c = droplower(b)
3×3 SparseMatrixCSC{Float64,Int64} with 2 stored entries:
[1, 1] = 0.5
[1, 2] = 1.0
julia> full(Symmetric(c)) # note this is symmetric although c isn't
3×3 Array{Float64,2}:
0.5 1.0 0.0
1.0 0.0 0.0
0.0 0.0 0.0
Operations on the SparseMatrixCSC often need to be customized for maximum efficiency. So, to get from a sparse matrix A to a symmetric sparse matrix with the same upper part, here is a custom version (it is a bit cryptic, but working):
function symmetrize(A::SparseMatrixCSC)
m,n = size(A)
m == n || error("argument expected to be square matrix")
rows = rowvals(A) ; vals = nonzeros(A)
a = zeros(Int,n) ; b = zeros(Int,n) ; c = 0
for i=1:n
for j in nzrange(A, i)
if rows[j]>=i
if rows[j]==i a[i] += 1 ; c += 1 ; end
break
end
a[i] += 1 ; b[rows[j]] += 1 ; c += 2
end
end
c == 0 && return SparseMatrixCSC(n, n, ones(n+1), nrows, nvals)
ncolptr = Vector{Int}(n+1)
nrows = Vector{Int}(c) ; nvals = Vector{eltype(A)}(c)
idx = 1
for i=1:n
ncolptr[i] = idx
if a[i]==0 a[i] = idx ; idx += b[i] ; continue ; end
for j in (0:a[i]-1)+first(nzrange(A, i))
nvals[idx] = vals[j] ; nrows[idx] = rows[j] ; idx += 1
rows[j] >= i && break
nvals[a[rows[j]]] = vals[j] ; nrows[a[rows[j]]] = i
a[rows[j]] += 1
end
a[i] = idx ; idx += b[i]
end
ncolptr[n+1] = idx
return SparseMatrixCSC(n, n, ncolptr, nrows, nvals)
end
And a sample run:
julia> f = sprand(5,5,0.2)
5×5 SparseMatrixCSC{Float64,Int64} with 5 stored entries:
[1, 1] = 0.981579
[3, 1] = 0.330961
[5, 1] = 0.527683
[4, 5] = 0.196898
[5, 5] = 0.579006
julia> full(f)
5×5 Array{Float64,2}:
0.981579 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0
0.330961 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.196898
0.527683 0.0 0.0 0.0 0.579006
julia> full(symmetrize(f))
5×5 Array{Float64,2}:
0.981579 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.196898
0.0 0.0 0.0 0.196898 0.579006
This version should be faster than others, but this still needs to be benchmarked (and some #inbounds added in the for loops).

Resources