The surprising results above are because length
is not defined for the Flatten
object returned by flatten
, which means that the size of the result cannot be determined in advance. If I define:
Base.length(fl::Base.Iterators.Flatten{<:AbstractVector{<:UnitRange}}) = sum(length, fl.it)
Base.iteratorsize(::Base.Iterators.Flatten{<:AbstractVector{<:UnitRange}}) = Base.HasLength()
then the benchmark results for the flatten
approach become
BenchmarkTools.Trial:
memory estimate: 61.00 MiB
allocs estimate: 5
--------------
minimum time: 21.147 ms (1.61% GC)
median time: 27.357 ms (20.71% GC)
mean time: 28.169 ms (22.88% GC)
maximum time: 90.278 ms (76.97% GC)
--------------
samples: 178
evals/sample: 1
Maybe a more general version of the methods above could make it into Base? We’re getting a lot of mileage out of this simple question.
(As an aside, how awesome is it that you can just tinker like this in Julia!)
Edit: Julia issue: https://github.com/JuliaLang/julia/issues/23431.