Filtering a dictionary in julia - julia

I want to filter a dictionary using filter() function but I am having trouble with it. What I wish to accomplish is, to return the key for some condition of the value. However I am getting a method error
using Agents: AbstractAgent
# Define types
mutable struct Casualty <: AbstractAgent
id::Int
ts::Int
rescued::Bool
function Casualty(id,ts; rescued = false)
new(id,ts,rescued)
end
end
mutable struct Rescuer <: AbstractAgent
id::Int
actions::Int
dist::Float64
function Rescuer(id; action = rand(1:3) , dist = rand(1)[1])
new(id,action,dist)
end
end
cas1 = Casualty(1,2)
cas2 = Casualty(2,3)
resc1 = Rescuer(3)
agents = Dict(1=> cas1, 2 => cas2, 3 => resc1)
Now to filter
filter((k,v) -> v isa Casualty, agents)
# ERROR: MethodError: no method matching (::var"#22#23")(::Pair{Int64, AbstractAgent})
# what I truly wish to achieve is return the key for some condition of the value
filter((k,v) -> k ? v isa Casualty : "pass", agents)
# ofcourse I am not sure how to "pass" using this format
Any idea how I can achieve this. Thanks

For dictionaries filter gets a key-value pair, so do either (destructuring Pair):
julia> dict = Dict(1=>"a", 2=>"b", 3=>"c")
Dict{Int64, String} with 3 entries:
2 => "b"
3 => "c"
1 => "a"
julia> filter(((k,v),) -> k == 1 || v == "c", dict)
Dict{Int64, String} with 2 entries:
3 => "c"
1 => "a"
or for example (getting Pair as a whole):
julia> filter(p -> first(p) == 1 || last(p) == "c", dict)
Dict{Int64, String} with 2 entries:
3 => "c"
1 => "a"
julia> filter(p -> p[1] == 1 || p[2] == "c", dict)
Dict{Int64, String} with 2 entries:
3 => "c"
1 => "a"
EDIT
Explanation why additional parentheses are needed:
julia> f = (x, y) -> (x, y)
#1 (generic function with 1 method)
julia> g = ((x, y),) -> (x, y)
#3 (generic function with 1 method)
julia> methods(f)
# 1 method for anonymous function "#1":
[1] (::var"#1#2")(x, y) in Main at REPL[1]:1
julia> methods(g)
# 1 method for anonymous function "#3":
[1] (::var"#3#4")(::Any) in Main at REPL[2]:1
julia> f(1, 2)
(1, 2)
julia> f((1, 2))
ERROR: MethodError: no method matching (::var"#1#2")(::Tuple{Int64, Int64})
Closest candidates are:
(::var"#1#2")(::Any, ::Any) at REPL[1]:1
julia> g(1, 2)
ERROR: MethodError: no method matching (::var"#3#4")(::Int64, ::Int64)
Closest candidates are:
(::var"#3#4")(::Any) at REPL[2]:1
julia> g((1, 2))
(1, 2)
As you can see f takes 2 positional argument, while g takes one positional argument that gets destructured (i.e. the assumption is that argument passed to g is iterable and has at least 2 elements).
See also https://docs.julialang.org/en/v1/manual/functions/#Argument-destructuring.
Now comes the tricky part:
julia> h1((x, y)) = (x, y)
h1 (generic function with 1 method)
julia> methods(h1)
# 1 method for generic function "h1":
[1] h1(::Any) in Main at REPL[1]:1
julia> h2 = ((x, y)) -> (x, y)
#1 (generic function with 1 method)
julia> methods(h2)
# 1 method for anonymous function "#1":
[1] (::var"#1#2")(x, y) in Main at REPL[3]:1
In this example h1 is a named function. In this case it is enough to just wrap arguments in extra parentheses to get destructuring behavior. For anonymous functions, because of how Julia parser works an extra , is needed - if you omit it the extra parentheses are ignored.
Now let us check filter docstring:
filter(f, d::AbstractDict)
Return a copy of d, removing elements for which f is false.
The function f is passed key=>value pairs.
As you can see from this docstring f is passed a single argument that is Pair. That is why you need to use either destructuring or define a single argument function and extract its elements inside the function.

The right syntax is:
filter(((k,v),) -> v isa Casualty, agents)
which prints
julia> filter(((k,v),) -> v isa Casualty, agents)
Dict{Int64, AbstractAgent} with 2 entries:
2 => Casualty(2, 3, false)
1 => Casualty(1, 2, false)
About the problem of only getting involved keys... I have no idea beside:
julia> filter(((k,v),) -> v isa Casualty, agents) |> keys
which prints
julia> filter(((k,v),) -> v isa Casualty, agents) |> keys
KeySet for a Dict{Int64, AbstractAgent} with 2 entries. Keys:
2
1

Related

How to append to an empty list in Julia?

I want to create an empty lsit and gardually fill that out with tuples. I've tried the following and each returns an error. My question is: how to append or add and element to an empty array?
My try:
A = []
A.append((2,5)) # return Error type Array has no field append
append(A, (2,5)) # ERROR: UndefVarError: append not defined
B = Vector{Tuple{String, String}}
# same error occues
You do not actually want to append, you want to push elements into your vector. To do that use the function push! (the trailing ! indicates that the function modifies one of its input arguments. It's a naming convention only, the ! doesn't do anything).
I would also recommend creating a typed vector instead of A = [], which is a Vector{Any} with poor performance.
julia> A = Tuple{Int, Int}[]
Tuple{Int64, Int64}[]
julia> push!(A, (2,3))
1-element Vector{Tuple{Int64, Int64}}:
(2, 3)
julia> push!(A, (11,3))
2-element Vector{Tuple{Int64, Int64}}:
(2, 3)
(11, 3)
For the vector of string tuples, do this:
julia> B = Tuple{String, String}[]
Tuple{String, String}[]
julia> push!(B, ("hi", "bye"))
1-element Vector{Tuple{String, String}}:
("hi", "bye")
This line in your code is wrong, btw:
B = Vector{Tuple{String, String}}
It does not create a vector, but a type variable. To create an instance you can write e.g. one of these:
B = Tuple{String, String}[]
B = Vector{Tuple{String,String}}() # <- parens necessary to construct an instance
It can also be convenient to use the NTuple notation:
julia> NTuple{2, String} === Tuple{String, String}
true
julia> NTuple{3, String} === Tuple{String, String, String}
true

Best way to eval in a given scope / context which is in the form of a Dict?

I have a string, e.g. z[2] and I want to eval it in a context, e.g. Dict(:z => 1:10)
What's the best way to do it?
I can make it sort of work, but it is very slow.
function replace_expr(expr, d::Dict)
return expr
end
function replace_expr(s::Symbol, d::Dict)
get(d, s, s)
end
function replace_expr(expr::Expr, d::Dict)
return Expr(replace_expr(expr.head, d),
[replace_expr(e, d) for e in expr.args]...)
end
function eval_with(context::Dict{Symbol, Any}, expr_string::AbstractString)
# E.g. :abc => :(s[:abc])
d = Dict(k => :(s[$(Meta.quot(k))]) for k in keys(context))
ex = parse("s -> $expr_string")
ex = replace_expr(ex, d)
return eval(ex)(context)
end
The following is the test
function make_context()
x = 1
y = "foo"
z = 2:5
Dict(
:x => x,
:y => y,
:z => z
)
end
const context = make_context()
#test eval_with(context, "x + 3") == 4
#test eval_with(context, "string(1, y, 1)") == "1foo1"
#test eval_with(context, "z[2]") == 3
#time eval_with(context, "z[2]")
# 0.004739 seconds (767 allocations: 40.728 KB)
This seems like a place where you can lean upon more of Julia's built-in expression evaluation machinery. eval takes an optional argument: the module in which the evaluation is to occur.
You can create new modules programmatically:
julia> M = Module()
anonymous
And you can assign values from a dictionary into that module with eval:
julia> context = Dict(
:x => 1,
:y => "foo",
:z => 2:5
);
julia> for (k,v) in context
eval(M, :($k = $v))
end
julia> M.x
1
julia> M.y
"foo"
And now, of course, you can evaluate your custom string within the context of your module.
julia> eval(M, parse("x+3"))
4
julia> eval(M, parse("string(1, y, 1)"))
"1foo1"
Dynamic evaluation like this is not going to be a place where Julia shines. I think this will be about as good as it gets:
julia> #time eval(M, parse("z[2]"))
0.000284 seconds (13 allocations: 672 bytes)
3
Note that this has slightly different semantics from the code you wrote above; the variables within your context only got populated at the beginning… and might be changed by a new evaluation.
And the usual caveats about using eval apply. There are often other, better ways of structuring your program that will be more performant, more understandable, and more maintainable.
If you know the values in advance, you can get around using eval via metaprogramming. A macro for this is provided by Parameters.jl:
d = Dict{Symbol,Any}(:a=>5.0,:b=>2,:c=>"Hi!")
#unpack a, c = d
a == 5.0 #true
c == "Hi!" #true

What do the triple dots (...) in a julia array do? Why do they change the type signature?

Given the data types bellow, the following comprehension yields two Array{Any,1} of Players:
[[team.players for team in [big_team_1, big_team_2]]]
This next comprehension, however, yields the desired result of an Array{Player,1} of 12 elements:
[[team.players for team in [big_team_1, big_team_2]]...]
What exactly is the ... doing? Where is this documented?
Data:
type Player
ranking::Int
end
type Team
players::Array{Player}
end
team_1 = Team([Player(10_000), Player(11_000), Player(9_000), Player(8_500),
Player(20_000), Player(10_500)])
team_2 = Team([Player(i.ranking + 3000) for i in team_1.players])
args... and ; kwargs... is the splat operator, if you know Python, it's the same as *args and **kwargs:
You can find documentation here: What does the splat ... operator do?
When in method signature (collects arguments).
julia> function foo(pos_1, pos_2, opt_1 = :opt_1, args...;
opt_kw1 = :opt_kw1, opt_kw2 = :opt_kw2, kwargs...)
[pos_1, pos_2, opt_1, args, opt_kw1, opt_kw2, (kwargs,);]
end
foo (generic function with 2 methods)
This signature means:
pos_1 is the first required positional argument.
pos_2 is the second required positional argument.
opt_1 is an optional positional argument.
args... are all the following positional arguments, collected in a tuple.
Notice how semi colon ; separates positional arguments from keyword arguments (order is not important in key word arguments):
opt_kw1 is an optional keyword argument.
opt_kw2 is an optional keyword argument.
kwargs... are all the following keyword arguments collected in an array of tuple (key, value) pairs.
julia> methods(foo)
# 2 methods for generic function "foo":
foo(pos_1, pos_2) at none:3
foo(pos_1, pos_2, opt_1, args...) at none:3
foo can be called like this:
Required arguments:
julia> foo(:pos_1, :pos_2)
7-element Array{Any,1}:
:pos_1 # provided value
:pos_2 # provided value
:opt_1 # default value
() # empty tuple
:opt_kw1 # default value
:opt_kw2 # default value
(Any[],) # there are no kwargs
Optional positional and keyword arguments:
julia> foo(:pos_1, :pos_2, :OPT_1, :a, :b, :c,
opt_kw2 = :OPT_KW2, kwarg1 = true, opt_kw1 = :OPT_KW1, kwarg2 = false)
7-element Array{Any,1}:
:pos_1
:pos_2
:OPT_1
(:a,:b,:c)
:OPT_KW1
:OPT_KW2
(Any[(:kwarg1,true),(:kwarg2,false)],)
Notice how the order in key word arguments is not relevant, also the semicolon ; is not needed when calling the function.
When in function call (spreads arguments).
Using collections for the positional arguments and assosiative collections with symbol keys for the keyword arguments:
julia> x, y, z = 1, 2, 3;
julia> sum(x, y, z)
ERROR: MethodError: `sum` has no method matching sum(::Int64, ::Int64, ::Int64)
Closest candidates are:
sum(::Union{Base.Func{1},Function}, ::AbstractArray{T,N}, ::Any)
sum(::Union{Base.Func{1},DataType,Function}, ::Any)
sum(::BitArray{N}, ::Any)
...
julia> sum
sum (generic function with 12 methods)
julia> Base.sum(args...) = sum(args)
sum (generic function with 13 methods)
julia> sum(x, y, z)
6
julia> foo(x, y, z) = sum(x, y, z)
foo (generic function with 1 method)
julia> foo(x, y, z)
6
julia> foo([x, y, z])
ERROR: MethodError: `foo` has no method matching foo(::Array{Int64,1})
Closest candidates are:
foo(::Any, ::Any, ::Any)
julia> foo([x, y, z]...)
6
julia> foo(; x = 0, y = 0, z = 0) = sum(x, y, z)
foo (generic function with 2 methods)
julia> foo()
0
julia> foo(z = 3, x = 1, y = 2)
6
julia> foo(; Dict(:z => 3, :y => 2, :x => 1))
ERROR: TypeError: anonymous: in typeassert, expected Symbol, got Pair{Symbol,Int64}
in anonymous at no file
julia> foo(; Dict(:z => 3, :y => 2, :x => 1)...)
6

Julia-Lang Metaprogramming: turn expression into function with expression-dependent arguments

Given a dictionary of values,
values = {:A => 3, :B => 1}
turn an (arbitrary) expression like
expr = :(2*A)
into a function foo(values) that evaluates the expression, so in this case foo(values) = 6. The resulting function will be called millions of times, so speed is an important consideration. I am happy to adopt a slightly different approach if necessary, as long as it can be automatised.
Things I tried:
The conversion using convert(Function, expr), as suggested here. Fails for me (Julia 0.3.8-pre):
convert has no method matching convert(::Type{Function}, ::Expr)
Using #eval one can do
#eval foo(A) = $(expr)
and then call foo(values[:A]), but that would require knowing that expr depends on A (and only on A).
I wrote a function find_vars(exp) to return the symbols in expr (in this case [:A]), but couldn't find how to use them in the #eval approach.
Base.Cartesian has an unexported function lreplace which may be what you're after. Then you can do something like:
julia> values = Dict(:A=>3, :B=>1)
Dict{Symbol,Int64} with 2 entries:
:B => 1
:A => 3
julia> import Base.Cartesian.lreplace
julia> expr = :(2*A)
:(2A)
julia> function lreplace_all(expr, d)
for (k, v) in d
expr = lreplace(expr, k, v)
end
expr
end
lreplace_all (generic function with 1 method)
julia> lreplace_all(expr, values)
:(2 * 3)
julia> #eval foo(A) = $(lreplace_all(:(2A), values))
foo (generic function with 1 method)
julia> foo(1)
6
Although, since A is defined by the values dict, it makes more sense to define foo as a zero-argument function (unless I've missed something).
EDIT:
After rereading your question it seems like you want to pass in the actual dictionary to the function rather than have the values available at compile time as I've done above. In that case, we have get a little creative:
First we need an lreplace like function that will work with expressions which is easy enough
julia> dictreplace!(ex, s, v) = ex
dictreplace! (generic function with 1 method)
julia> dictreplace!(ex::Symbol, s, v) = s == ex ? v : ex
dictreplace! (generic function with 2 methods)
julia> function dictreplace!(ex::Expr, s, v)
for i=1:length(ex.args)
ex.args[i] = dictreplace!(ex.args[i], s, v)
end
ex
end
dictreplace! (generic function with 3 methods)
julia> dictreplace(ex, s, v) = dictreplace!(copy(ex), s, v)
dictreplace (generic function with 1 method)
Now we want to replace every occurence of a symbol in our dict keys with a dictionary lookup
julia> function dictreplace_all(expr, kys, dsym)
for k in kys
expr = dictreplace(expr, k, :($(dsym)[$(QuoteNode(k))]))
end
expr
end
dictreplace_all (generic function with 1 method)
julia> dictreplace_all(:(2A), keys(values), :d)
:(2 * d[:A])
julia> #eval foo(args) = $(dictreplace_all(:(2A), keys(values), :args))
foo (generic function with 1 method)
julia> values[:A] = -99
-99
julia> foo(values)
-198
Thanks to the solution by #ptb and another metaprogramming question I found a simpler yet slower solution:
function foo(values, expr)
expr = quote
A = values[:A]
B = values[:B]
return $(expr)
end
eval(expr)
end
Reading in the values from the dictionary can also be done programmatically by replacing the inner evaluation by
$([:($k = $v) for (k, v) in values]...)
return $(expr)

Extracting parameter types in Julia

Suppose I write a function in Julia that takes a Dict{K,V} as an argument, then creates arrays of type Array{K,1} and Array{V,1}. How can I extract the types K and V from the Dict object so that I can use them to create the arrays?
Sven and John's answers are both quite right. If you don't want to introduce method type parameters the way John's code does, you can use the eltype function:
julia> d = ["foo"=>1, "bar"=>2]
["foo"=>1,"bar"=>2]
julia> eltype(d)
(ASCIIString,Int64)
julia> eltype(d)[1]
ASCIIString (constructor with 1 method)
julia> eltype(d)[2]
Int64
julia> eltype(keys(d))
ASCIIString (constructor with 1 method)
julia> eltype(values(d))
Int64
As you can see, there are a few ways to skin this cat, but I think that eltype(keys(d)) and eltype(values(d)) are by far the clearest and since the keys and values functions just return immutable view objects, the compiler is clever enough that this doesn't actually create any objects.
If you're writing a function that will do this for you, you can make the types a parameter of the function, which may save you some run-time lookups:
julia> function foo{K, V}(d::Dict{K, V}, n::Integer = 0)
keyarray = Array(K, n)
valarray = Array(V, n)
# MAGIC HAPPENS
return keyarray, valarray
end
foo (generic function with 2 methods)
julia> x, y = foo(["a" => 2, "b" => 3])
([],[])
julia> typeof(x)
Array{ASCIIString,1}
julia> typeof(y)
Array{Int64,1}
You can use keys and values in combination with typeof:
# an example Dict{K, V}
d = Dict{Int64, ASCIIString}()
# K
typeof(keys(d))
Array{Int64,1}
# V
typeof(values(d))
Array{ASCIIString,1}
If you are just interested in the types, you can use eltype(d), or define even more specific functions
keytype{K}(d::Dict{K}) = K
valuetype{K,V}(d::Dict{K,V}) = V
and find the type immediately through
keytype(d)
valuetype(d)
As far as I understand, this should be pretty efficient because the compiler can deduce most of this at compile time.
For iterables, the eltype approach that is already given in other answers works well enough. E.g.
julia> d = Dict(:a => 1, :b => 2)
Dict{Symbol, Int64} with 2 entries:
:a => 1
:b => 2
julia> K, V = eltype(keys(d)), eltype(values(d))
(Symbol, Int64)
julia> K
Symbol
julia> V
Int64
This approach is generalisable to all iterables. However I would like to offer another approach which will generalise to other kinds of object (and still doesn't use the method type signature approach):
julia> d = Dict(:a => 1, :b => 2)
Dict{Symbol, Int64} with 2 entries:
:a => 1
:b => 2
julia> typeof(d)
Dict{Symbol, Int64}
julia> K, V = typeof(d).parameters
svec(Symbol, Int64)
julia> K
Symbol
julia> V
Int64
You can see that the Dict{Symbol, Int64} type has a field parameters which you can unpack to obtain the type parameters. This works on structs too:
julia> struct MyStruct{S, T}
a::S
b::T
end
julia> x = MyStruct(1, 1.0)
MyStruct{Int64, Float64}(1, 1.0)
julia> S, T = typeof(x).parameters
svec(Int64, Float64)
julia> S
Int64
julia> T
Float64

Resources