I am currently trying to build a program where I have a recursive function that for every loop appends one new element to the array it is building. I didn't want to use the append function that many times, because my function is supposed to do a large number of loops, and I've come to learn from previous experiences that the append function in general takes a lot of time. I've tried to look everywhere for a function that simply adds one element to the tail of the array, but I've found nothing of such sort. So I was thinking I would ask here.
So my question is basically: "Is there a more effective way of adding one element to the back of an array than using append?"
So I used a list instead, inserting each new element as a head, and reverted the list when the function was finished. This made the function about 70 times faster. But the problem remains as I have another function that does pretty much the same, which became about 4 times slower, increasing the overall time for my main function. The functions are very similar. The first function (the one that became much faster) produces ints, adding each new int to the list. The second function (the one that became much slower) produces an object, adding each new object to the list. Does anyone have an idea why one function became so much faster while the other one became so much slower?
If you are using array module, you can use the concatenation using the + operator, append(), insert(), and extend() functions to add elements to the array. If you are using NumPy arrays, use the append() and insert() function.
ResizeArray is a more efficient data structure for this task, for example:
let filterRange predicate (i, j) =
let results = ResizeArray(j-i+1)
for k = i to j do
if predicate k then results.Add(k)
results.ToArray()
ResizeArray module from F# PowerPack provides high-order functions to manipulate ResizeArray
in a functional way. However, beware that these functions create new ResizeArray
instances which make them less efficient than .NET methods.
A purely functional alternative is to use a list as an accumulator, prepend elements to the accumulator, reverse it (if the order matters) and convert to Array in the end:
let filterRange predicate (i, j) =
let rec loop k acc =
if k = j+1 then acc
elif predicate k then loop (k+1) (k::acc)
else loop (k+1) acc
loop i [] |> List.rev |> Array.ofList
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With