Yesterday I wrote about list in F#. Today I’ll write about arrays, which unlike lists are a mutable flat storage and cannot be resized. That means you have to create a new array if you want to remove or add elements. Advantages include constant look-up time and the fact that they can store a large amount of data.
You can create a literal array in a similar way with the lists, placing the elements between [| |]:
let data1 = [|1;2;3;4|] printfn "data1: %a" output_any data1
data1: [|1; 2; 3; 4|]
The empty literal array is [||].
To create an array you can either use Array.create or Array.init. They both create and initialize an array, but the second makes a lambda expression, which allows advance initialization possibilities. The following creates an array with 10 elements initialized to 1:
let data2 = Array.create 10 1 printfn "data2: %a" output_any data2
Here is the output:
data2: [|1; 1; 1; 1; 1; 1; 1; 1; 1; 1|]
The same can be achieved using Array.init:
let data3 = Array.init 10 (fun x -> 1) printfn "data3: %a" output_any data3
data3: [|1; 1; 1; 1; 1; 1; 1; 1; 1; 1|]
But we can use Array.init to initialize the elements from 1 to N for instance:
let data4 = Array.init 10 (fun x -> x+1) printfn "data4: %a" output_any data4
data4: [|1; 2; 3; 4; 5; 6; 7; 8; 9; 10|]
The arrays are mutable data structures. Elements are accessed with .[] or .(). The following code shows how to set the elements of an array:
let data5 = Array.create 10 0 for i = 0 to (Array.length data5)-1 do data5.[i] <- i+1 printfn "data5: %a" output_any data5
data5: [|1; 2; 3; 4; 5; 6; 7; 8; 9; 10|]
You can iterate over the elements of an array with Array.iter and Array.iteri, the second also providing access to the index of the elements.
data4 |> Array.iter (fun x -> printf "%d " x) printfn "" data4 |> Array.iteri (fun i x -> printfn "data4(%d) = %d" i x)
1 2 3 4 5 6 7 8 9 10 data4(0) = 1 data4(1) = 2 data4(2) = 3 data4(3) = 4 data4(4) = 5 data4(5) = 6 data4(6) = 7 data4(7) = 8 data4(8) = 9 data4(9) = 10
Retrieving the length of the array can either be done with Array.length arr or with arr.Length.
for i = 0 to data4.Length-1 do printfn "data4(%d) = %d" i data4.(i)
data4(0) = 1 data4(1) = 2 data4(2) = 3 data4(3) = 4 data4(4) = 5 data4(5) = 6 data4(6) = 7 data4(7) = 8 data4(8) = 9 data4(9) = 10
Like the lists, arrays provide mapping that creates a new array by applying a function on all the elements of an array (with Array.map) or two arrays (with Array.map2).
let data6 = data4 |> Array.map (fun x -> x*2) printfn "data6: %a" output_any data6 let data7 = Array.map2 (fun x y -> x+y) data4 data6 printfn "data7: %a" output_any data7
data6: [|2; 4; 6; 8; 10; 12; 14; 16; 18; 20|] data7: [|3; 6; 9; 12; 15; 18; 21; 24; 27; 30|]
A copy of an array can be done with Array.copy.
let data7 = Array.copy data6 printfn "data7: %a" output_any data7
data7: [|2; 4; 6; 8; 10; 12; 14; 16; 18; 20|]
Appending elements to an array is also possible with Array.append, but the result is a new array, created by concatenating two arrays.
let data8 = Array.append data7 [|100|] printfn "data8: %a" output_any data8
data8: [|2; 4; 6; 8; 10; 12; 14; 16; 18; 20; 100|]
The last operation of arrays I'm going to mention here is the folding, which allows applying a function to all the elements of an array, threading an accumulator argument in the process. The following example shows how to compute the sum of the elements of an array.
let data9 = [|1;2;3;4|] let sum1 = (Array.fold_left (fun acc x-> x + acc) 0 data9) let sum2 = (Array.fold_right (fun acc x-> x + acc) data9 0) printfn "sum1 = %d" sum1 printfn "sum2 = %d" sum2
sum1 = 10 sum2 = 10
let sum1 = (Array.fold_left (fun acc x-> x + acc) 0 data9)
let sum2 = (Array.fold_right (fun acc x-> x + acc) data9 0)
Why is the prototype different for this 2 functions ?
I mean fold_left acc arr and fold_right arr acc ?
I thought the difference was only in how you move in the array..
Track back from http://bogdandotnet.blogspot.com/2009/04/multi-dimensional-arrays-vs-arrays-of.html 🙂
Hi, I must receive the data (an unknown number of obj)
Considering that I will have access to the input in order:
1- what’s most efficient to use between list and array??
2- Using the attribute is equivalent to using a normal array?
Thanks
Arrays are fixed size sequences. If you don’t know the length in advance, then you ought to use a list, which is a variable size sequence. Unless you want to allocate an array big enough to hold all the objects, but that will probably mean waste a memory. So it depends what kind of efficiency you are looking for.
yes, i know. But this isn’t a problem because the size is fixed by the sender; there isn’t waste of memory.
I declare: let x (param: Object[] or Object list) and then flow once the seq.. The sender can allocate an array of 3 or 50 Object or (equivalently??) a linked list..
Then, I’m interested to the “ParamArray” attribute: allows only a differente syntax or are there differences in terms of efficiency?
Again, depends on what kind of “efficiency” you’re looking for. Arrays are accessed through an index, so access time is constant; on the other side, linked lists had to be traversed each time you need to access some element. On the other side, lists are immutable, which means whenever you make a change (add, remove a node) a new list is created. Arrays are mutable.
Hi, I need to do an Array of struct. Is it possible? And how? Thanks.