I have CircularBuffer (sorted) array, and want to insert the value into it. A simple example is
cb = CircularBuffer{Float64}(5)
#when full capacity
append!(cb, [1.0, 2.0, 3.0, 4.0, 5.0])
ii = searchsortedlast(cb, 3.5)
copyto!(cb, [cb[2:ii]; 3.5])
#when not full capacity
empty!(cb)
append!(cb, [2.0, 3.0, 4.0, 5.0])
ii = searchsortedlast(cb, 3.5)
#want to have cb = [2.0, 3.0, 3.5, 4.0, 5.0]
With full capacity, I use copyto! to get the result (although not sure if the most efficient way), but I can’t figure it out when the array is not full capacity. Also, this is inside of several for loops, so the speed is essential. I would appreciate if you give some help.
From the details here this seems like a heap would be a better choice. That is, if you just want to maintain the n-largest elements from some process and get them sorted at the end.
using DataStructures
h = BinaryHeap{Float64, DataStructures.FasterForward}(1.0:5.0) # improved performance for floats
function push_with_cap!(heap, item, cap)
push!(heap, item)
while length(heap) > cap
pop!(heap)
end
end
push_with_cap!(h, 3.5, 5)
...
# get elements in sorted order
extract_all!(h)
If you actually need to maintain a sorted list between insertions I’m not sure that a CircularBuffer is going to help and you probably won’t do much better than just maintaining a sorted vector
function push_with_cap!(v, item, cap)
ii = searchsortedlast(v, item; rev=true)
insert!(v, ii+1, item)
while length(v) > cap
pop!(v)
end
end
buf = Float64[]
sizehint!(buf, capacity+1)
append!(buf, 1.0:5.0)
sort!(buf; rev=true)
push_with_cap!(buf, 3.5, 5)
Since it is more efficient to add and remove from the end of a vector we maintain it in reverse order.
HTH
1 Like