From 5ef5fb3cd0588df1ed93cb0f504bdacbf887d73a Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Fri, 27 Jan 2023 16:59:02 +0100 Subject: [PATCH] less push! in collect_with_eltype --- src/geometry_primitives.jl | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/geometry_primitives.jl b/src/geometry_primitives.jl index b2ae6d42..bdb4a3b8 100644 --- a/src/geometry_primitives.jl +++ b/src/geometry_primitives.jl @@ -74,15 +74,32 @@ collect_with_eltype(::Type{T}, vec::Vector{T}) where {T} = vec collect_with_eltype(::Type{T}, vec::AbstractVector{T}) where {T} = collect(vec) function collect_with_eltype(::Type{T}, iter) where {T} - # TODO we could be super smart about allocating the right length - # but its kinda annoying, since e.g. T == Triangle and first(iter) isa Quad - # will need double the length etc - but could all be figured out ;) - result = T[] + # We need to get `eltype` information from `iter`, it seems to be `Any` + # most of the time so the eltype checks here don't actually work + l = if Base.IteratorSize(iter) isa Union{Base.HasShape,Base.HasLength} + if Base.IteratorEltype(iter) isa Base.HasEltype && isconcretetype(eltype(iter)) + # Work out the exact length + length(convert_simplex(T, first(iter))) * length(iter) + else + # We know it is at least the length of iter, + # after that we will `push!` if we have to + length(iter) + end + else + 0 + end + n = 0 + result = Vector{T}(undef, l) for element in iter # convert_simplex always returns a tuple, # so that e.g. convert(Triangle, quad) can return 2 elements for telement in convert_simplex(T, element) - push!(result, telement) + n += 1 + if n > l + push!(result, telement) + else + result[n] = telement + end end end return result