1634
July 16, 2020, 10:03pm
1
Hi,
For some very simple function like +=1 if the element of this array is 0, is there any concise way?
c=[0,1,0]
map(x->x=0, c) #but I wish to add a **if** in this one-line for loop
#otherwise how verbose my usual solution is:
function plusone(c) #empirically saying, need to make it a function for outputing
#the changed variable to main macro (instead of losing)
for i in 1:length(c)
if i == 0
c[i] = 1
end
return c #output make no dif
end
end
3 Likes
In general, you can use &&
as an if condition as in i==0 && c[i]+=1
(||
as well)
In this case, you could also do
for i in 1:length(c)
c[i] += (c[i] == 0)
end
It should also be noted that the function is not the same as the original map
. map
does not modify c
in place. You could do map!(x -> x + (x==0), c, c)
for the same effect though.
It is almost always possible to condense short for loops and if conditions into a single line, but it’s not often worth it IMO.
1 Like
DNF
July 16, 2020, 10:22pm
4
Your code example does not match your question.
I will use your written question, which is to replace zeros with ones. In that case you should use the replace!
function:
replace!(c, 0=>1)
3 Likes
A generic approach
c .= ifelse.(c .== 0, 1, c)
5 Likes
This has the downside of making several copies.
If you’re referring to the c .= ...
solution above , that works in-place with no copies or temporary arrays.
2 Likes
Yeah, I tried to delete, but messed up since I’m on a phone atm
1634
July 17, 2020, 9:57am
9
#Comparison
using BenchmarkTools
c=[0,1,0]
@btime map!(x -> x + (x==0), c, c) #25.426 ns (0 allocations: 0 bytes)##perform the best
c=[0,1,0]
@btime map(x-> x==0 ? 1 : x, c) #288.844 ns (2 allocations: 128 bytes)
c=[0,1,0]
@btime c .= ifelse.(c .== 0, 1, c) # 774.766 ns (4 allocations: 96 bytes)
1 Like
oheil
July 17, 2020, 10:55am
10
Due to the small array and the very low timings these results are misleading:
julia> c=rand(Bool,100000);
julia> @benchmark map!(x -> x + (x==0), $c, $c)
BenchmarkTools.Trial:
memory estimate: 0 bytes
allocs estimate: 0
--------------
minimum time: 78.399 μs (0.00% GC)
median time: 78.600 μs (0.00% GC)
mean time: 84.175 μs (0.00% GC)
maximum time: 284.300 μs (0.00% GC)
--------------
samples: 10000
evals/sample: 1
julia> @benchmark map(x-> x==0 ? 1 : x, $c)
BenchmarkTools.Trial:
memory estimate: 97.78 KiB
allocs estimate: 3
--------------
minimum time: 91.101 μs (0.00% GC)
median time: 116.000 μs (0.00% GC)
mean time: 119.357 μs (3.91% GC)
maximum time: 6.092 ms (95.87% GC)
--------------
samples: 10000
evals/sample: 1
julia> @benchmark c .= ifelse.($c .== 0, 1, $c)
BenchmarkTools.Trial:
memory estimate: 96 bytes
allocs estimate: 4
--------------
minimum time: 90.599 μs (0.00% GC)
median time: 90.700 μs (0.00% GC)
mean time: 92.172 μs (0.00% GC)
maximum time: 300.601 μs (0.00% GC)
--------------
samples: 10000
evals/sample: 1
Still the first variant is best.
But what you actually do is:
julia> @benchmark trues(100000)
BenchmarkTools.Trial:
memory estimate: 12.41 KiB
allocs estimate: 2
--------------
minimum time: 460.000 ns (0.00% GC)
median time: 1.710 μs (0.00% GC)
mean time: 2.379 μs (14.36% GC)
maximum time: 180.490 μs (98.80% GC)
--------------
samples: 10000
evals/sample: 10
or in our case
julia> trues(3)
3-element BitArray{1}:
1
1
1
I guess its only a MWE for something more complex
1 Like
nilshg
July 17, 2020, 10:58am
11
I think you also need to interpolate the global variable into the benchmarking expression:
julia> c=rand(0:1, 100_000);
julia> @btime map!(x -> x + (x==0), $c, $c);
50.999 μs (0 allocations: 0 bytes)
julia> @btime map(x-> x==0 ? 1 : x, $c);
73.101 μs (3 allocations: 781.34 KiB)
julia> @btime $c .= ifelse.($c .== 0, 1, $c);
51.399 μs (0 allocations: 0 bytes)
3 Likes
oheil
July 17, 2020, 11:01am
12
Didn’t I? oh, I forgot one. Timings don’t change on my PC.
1 Like
nilshg
July 17, 2020, 11:03am
13
Sorry I actually missed that you did - I copied @1634 ’s example, and saw large differences between interpolated/not interpolated.
1 Like
Why in second test case map
is used instead of map!
? It looks like different things are compared.
1634
July 17, 2020, 7:47pm
15
What’s the purpose of having interpolation of global variable into the benchmark? Is this for mimicing the indexing of variable in a function or macro?