How to get vector from set of ranges?

I am trying to create a vector using in-line for loop.

indices = [2,5,6,8]
[i:i+6; for i in indices]

which returns

4-element Vector{UnitRange{Int64}}:
2:8
5:11
6:12
8:14

How to create vector of values instead of ranges?

You mean like this?

julia> reduce(vcat, [i:i+6 for i in indices])
28-element Vector{Int64}:
  2
  3
  4
  5
  6
  7
  8
  5
  6
(...)
1 Like

Sorry actually you don’t even need the array comprehension as reduce accepts a generator, so this will likely be more efficient:

reduce(vcat, i:i+6 for i in indices)
2 Likes

another way to —

vcat((:).(indices,indices.+6)...)
1 Like

Something like this should work and may be faster yet:

[ i+j for j in 0:6 for i in indices ]

(not tested, I may get the index order wrong).

(But I guess reduce (vcat,…) does not allocate any intermediate either?)

1 Like

I see:

julia> @btime reduce(vcat, i:i+6 for i in $indices)
  156.910 ns (9 allocations: 880 bytes)

and

julia> @btime [ i+j for j in 0:6 for i in $indices ]
  175.882 ns (4 allocations: 544 bytes)

:person_shrugging: (yours does get the indices wrong)

It also seems like the reduce trick actually doesn’t help here?

julia> @btime vcat([i:i+6 for i in $indices]...)
  136.101 ns (6 allocations: 544 bytes)

EDIT actually I only tried this because my subconscious reminded me that Frames was griping about this issue the other day:

https://github.com/JuliaLang/julia/issues/31636

2 Likes

:slightly_smiling_face: matlab influence:

julia> ([indices...;;] .+ [0:6...])[:]

1 Like

Just for completeness:

julia> inds = indices = [2,5,6,8]
4-element Vector{Int64}:
 2
 5
 6
 8

julia> @btime reduce(vcat, i:i+6 for i in $inds );
  208.478 ns (9 allocations: 880 bytes)

julia> @btime [ i+j for i in $inds for j in 0:6 ];
  240.907 ns (4 allocations: 544 bytes)

julia> function f(inds, range)
           v = Int[]
           for i in inds
               for j in range
                   push!(v, i+j)
               end
           end
           return v
       end
f (generic function with 2 methods)

julia> @btime f($inds, 0:6);
  199.283 ns (3 allocations: 480 bytes)

julia> function f2(inds, range)
           v = Vector{Int}(undef, length(range)*length(inds)) 
           ii = 0
           for i in inds
               for j in range
                 ii += 1
                 v[ii] = i + j  
               end
           end
           return v
       end
f2 (generic function with 1 method)

julia> @btime f2($inds, 0:6);
  47.373 ns (1 allocation: 288 bytes)

The only thing I don’t “like” is that f is faster than the comprehension, which I thought would be lowered to the same thing.

2 Likes