Is it possible to update Array elements in a list comprehension?

I found list comprehension is very useful tool.

Currently I encountered a problem. Say there is an array of 5 integers named TEST. I want to add 1 to randomly selected elements of TEST for 10 times and see if there is a zero in the result.

I can do it in a normal loop, but my question is if I can do it using comprehension?

julia> TEST = zeros(Int,5)
5-element Array{Int64,1}:
 0
 0
 0
 0
 0

#if I do the following, a error message jumps.
julia> TEST[rand(1:5)] += 1 for i in 1:10
ERROR: syntax: extra token "for" after end of expression
Stacktrace:
 [1] top-level scope at REPL[72]:1
 [2] include_string(::Function, ::Module, ::String, ::String) 
at .\loading.jl:1088

# and if I enclose the expression with (), it returns a generator.
julia> (TEST[rand(1:5)] += 1 for i in 1:10)
Base.Generator{UnitRange{Int64},var"#43#44"}(var"#43#44"(), 1:10)

Please help me out and tell me how to update array elements using comprehension.

Try enclosing the expression in square brackets.

[TEST[rand(1:5)] += 1 for i in 1:10]

In Julia, they’re called ‘array comprehensions’.

Thanks a lot for your quick response. I think it solved my problem! :smiley:

Note that using an array comprehension for this allocates an unnecessary array; it would be simpler and faster to use a loop:

for i = 1:10
    TEST[rand(1:5)] += 1
end

or, if you care about performance, put it in a function:

function randinc!(a, trials)
    r = eachindex(a)
    for i = 1:trials
        a[rand(r)] += 1
    end
    return a
end

and then call randinc!(TEST, 10).

There’s nothing wrong with loops in Julia. Loops are fast and often convenient!

(Just noticed that you already realized this. I’m not sure why you want to use a comprehension for this?)

You may also be thinking of a generator expression, which you can create by using parentheses:

julia> (TEST[rand(1:5)] += 1 for i in 1:10)
Base.Generator{UnitRange{Int64},var"#11#12"}(var"#11#12"(), 1:10)

A generator expression doesn’t actually perform the loop, however; it merely returns an iterator that can be passed an argument to another function that performs the loop, such as foreach or sum:

julia> sum(TEST[rand(1:5)] += 1 for i in 1:10)
17

julia> foreach(identity, TEST[rand(1:5)] += 1 for i in 1:10)

(When it is passed as an argument, a generator expression doesn’t need the extra parentheses.)

It’s not clear what the point of using a generator, rather than a simple loop, would be in the contest, however.

4 Likes

Thank you for your advice, really helpful!