Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a method for adding a tail to an array that is more effective than append in F#?

Tags:

arrays

append

f#

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?"


Updated with a new question regarding the previous one

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?

like image 304
Marcus Åberg Avatar asked Apr 09 '12 13:04

Marcus Åberg


People also ask

How do you add a value to an array in Python?

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.


1 Answers

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
like image 70
pad Avatar answered Oct 16 '22 23:10

pad