Use get! to get all elements in array

Hi, I have question about function get!. So I have this lines:

d=Dict("1"=>[1,11], "2"=>[2], "3"=>[3,13,33])
a=["2","3","4","5"]
t=Tuple(a)

Can i use function “get” for my variable a and t? I mean get all elements which are in Array/Tuple and in key in my dictionary. I want to know if it’s possible do in one line. Without using any loops. Only put something in blank place below.

get!(d,  , ["66"])

or

get(d,   ,[*here i want number what we check if is in keys(d)* ])

PS: How format text to julia syntax?

you format text with backticks, ```, one backtick is for inline code and three backticks is for a block of code

1 Like

there are good functions for this: intersect and union

d=Dict("1"=>[1,11], "2"=>[2], "3"=>[3,13,33])
a=["2","3","4","5"]
xx = intersect(a,keys(d)) # ["2","3"]
map(x->d[x],intersect(a,keys(d)))  #one liner
#all the elements of the dictionary d that have a key in common with a

is good to note that is not necessary to do Tuple(a), it works with any iterable

Here’s a faster and still quite nice alternative

[d[x] for x in a if x in keys(d)]

Do you also need the ["66"] you put in one of the lines? Not sure exactly what output you want.

1 Like

I want to add new element to Dict, so i write if it’s posible using get!

Do you also need the ["66"] you put in one of the lines? Not sure exactly what output you want.

Yes my mistake, i mean for sure [any number] best if will be this one what i want to check, mean contain in keys(d) if not, add to Dict.

I still don’t quite get it. Could you write out the inputs and the expected output? I guess you have written down the inputs, but I still don’t know what the output should be.

#input
d=Dict("1"=>[1,11], "2"=>[2], "3"=>[3,13,33])
a=["2","3","4","5"]
#do get!(...)
#output
Dict{String,Array{Int64,1}} with 5 entries:
  "1" => [1, 11]
  "2" => [2]
  "3" => [3, 13, 33]
  "4" => [4]
  "5" => [5]

I want to do the same like this, only without using loop:

for val in a
   get!(d, val, [parse(Int64, val)]
end

sincerely, that looks very good. im looking for ways to do that in one line for now

jl> z = get!.((d,), a, [[parse(Int, x)] for x in a])
4-element Array{Array{Int64,1},1}:
 [2]        
 [3, 13, 33]
 [4]        
 [5]        

jl> d
Dict{String,Array{Int64,1}} with 5 entries:
  "4" => [4]
  "1" => [1, 11]
  "5" => [5]
  "2" => [2]
  "3" => [3, 13, 33]
1 Like

Why do you want to get rid of the for-loop? This looks quite readable, and in Julia, there’s nothing wrong with just using a for-loop. You might be coming from Python, where native loops are quite slow, but in Julia, these don’t come at any extra cost compared to broadcasting, for example, so you are free to use whatever feels more natural.

2 Likes

this only modifies the dict

foreach(val->get!(d, val, [parse(Int64, val)]),a)

i was reading the julia documentation :smile: ,is only one line as requested, but your loop is the most elegant solution in my opinion (and in julia, that will run pretty fast)

1 Like

I reading about tuples and using it in function like do_sth(tuple…) and i think how write this in one line. If is possible do something not only for one element like get(Dict, element, new_value) but for more than one element like get(Dict, tuple…, new_val)(yep i know this syntax isn’t correct).
I coming from C++ :smiley:

You can just omit the square brackets around the generator expression, which will also make it non-allocating.

I did try that, but got identical runtime and allocations.

That is, I tried

get!.((d,), a, ([parse(Int, x)] for x in a))

I’m surprised I get a generator without the parens around the expression…

julia> @btime get!.((d,), $a, ([parse(Int, x)] for x in $a)) setup=(d=Dict("1"=>[1,11], "2"=>[2], "3"=>[3,13,33]))

  512.271 ns (11 allocations: 688 bytes)

julia> @btime get!.((d,), $a, [parse(Int, x)] for x in $a) setup=(d=Dict("1"=>[1,11], "2"=>[2], "3"=>[3,13,33]))
  507.953 ns (11 allocations: 688 bytes)

julia> @btime get!.((d,), $a, [[parse(Int, x)] for x in $a]) setup=(d=Dict("1"=>[1,11], "2"=>[2], "3"=>[3,13,33]))

  509.099 ns (11 allocations: 688 bytes)
  

You seem to be referring to argument splatting in functions. Have you read this section in the docs?

https://docs.julialang.org/en/v1/manual/functions/#Varargs-Functions-1

This syntax is very powerful in a lot of cases, but it doesn’t really seem applicable here. The purpose of splatting is just to pass the elements of an iterable to a function as different arguments, but there aren’t any methods defined for get! with more than three arguments, so this will just throw an error.

1 Like

I’m not 100% sure what is going on here, but I don’t know how representative such a micro-benchmark is, since you’re measuring a lot of different things here. The compiler might even be able to do some fancy stuff for small collections, but I would still recommend lazy generators for most applications, since the compiler doesn’t have to allocate the whole array on the heap.