# Quick 'for' and 'if' one-line loop

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

`map(x-> x==0 ? 1 : x, c) `

4 Likes

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

#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

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

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

Didn’t I? oh, I forgot one. Timings don’t change on my PC.

1 Like

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.

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?

2 Likes

Thanks @nilshg for sharing the link. Unfortunately the link’s broken. Here’s a new one:
BenchmarkTools Manual, Sub-Heading:Interpolating values into benchmark expressions

1 Like