TopMenu

Arrays in F# – The Mutable collection

Arrays in F# are mutable data type. I started intentionally with this line because FSharp(F#) is a functional programming language and the paradigm of language promotes immutability. So Whenever there is a mutable type or value be careful with the usage. Let’s go back to main topic i.e. Arrays.

In this post we’ll see how to initialize, iterate, update and other manipulation that you can do with Arrays in FSharp(F#). In this post we’ll cover only one dimensional array. May be we can discuss 2D, 3D, and Jagged array in advanced array post of arrays in future.

Let’s have fun with playing around Arrays.

Static array initialization

In FSharp(F#) we initialize the array with following notations:

let fruits = [|"Apple"; "Orange"; "Grapes"|]

// or using every item in separate line without separator

let fruits = [|

        "Apple"

        "Orange"

        "Grapes"

    |]

Notice additional symbol | (pipe) used with square braces to declare the array. Also the separator is not , comma anymore but it’s ; semicolon. Array of integer sample and possible mistakes that can be done by a C# developer without getting any compile time error.

let arr = [| 1; 2; 3; 4 |]
 
Possible mistakes #1  
// most common mistakes done by developers with background of imperative language
let arr1 = [| 1, 2, 3|]
// this is an array of tuples with one element, so no error is displayed.
// the ',' separator is used to create tuples.
 
Possible mistakes #2 
// what if the | is not used in declaration
let arr2 = [1; 2; 3]
// this is also valid but this would be a list and it's "IMMUTABLE"

Initialization using sequence expressions

// Array of squares of positive integers from 1 to 10
let arr3 = [| for i in 1 .. 10 -> i * i |]
Output -  [|1; 4; 9; 16; 25; 36; 49; 64; 81; 100|]  

Initialization using Array module

Array.empty : creates a new array that does not contain any elements.

// Specify the type by using a type argument.
let array1 = Array.empty<int>
// Specify the type by using a type annotation.
let array2 : int array = Array.empty
 
// Even though array3 has a generic type,
// you can still use methods such as Length on it.
let array3 = Array.empty
printfn "Length of empty array: %d" array3.Length

Output - 0

Array.create : creates an array of a specified size and sets all the elements to provided values.

// creates an array of length 10, all elements initialized with default value -1
let arrayOfTenZeroes : int array = Array.create 10 -1
// create a bool array with default value as true
let primeFlaggedArr : bool array = Array.create 10 true

Note – In the end of this article we’ll solve the find prime number problem using Sieve of Eratosthenes.

Array.zeroCreate : creates an array, given a dimension and a function to generate the elements.

// create a bool array with default values(false)
let primeFlaggedArr : bool array = Array.zeroCreate 10

Array.init : creates an array, given a dimension and a function to generate the elements.

// Another way to create array of squares starting from 1 to 10
printfn "Array of squares: %A" (Array.init 10 (fun index -> index * index))

Accessing array elements

You can access array elements by using a dot operator (.) and brackets ([ and ]).

let fruits = [|
        "Apple"
        "Orange"
        "Grapes"
    |]
 
let firstFruit = fruits.[0]

Accessing range of values from array using sliced notation

// Accesses elements from 0 to 2.
arr.[0..2]  
// esses elements from the beginning of the array to 2.
arr.[..2] 
// esses elements from 2 to the end of the array.
arr.[2..] 

Few more honorable mentions or generally used functions are Array.get, Array.set and Array.length which are self-explanatory.

Replacing existing value using index

Arrays are mutable so you can replace any existing value by accessing it via index and assigning a new value with ‘<-‘ operator.

// Updating the value of an item in array using index
let fruits1 = [|
        "Apple"
        "Orange"
        "Grapes"
    |]
 
fruits1.[0] <- "Mango"
 
let print = 
    for (fruit) in fruits1 do
        printfn "%s" fruit

 

Output –

> PrintUpper [|"Apple"; "Orange"; "Grapes"|] ;;

APPLE

ORANGE

GRAPES

Iterating through array elements

Let’s create a function that takes an array of string and convert the values to upper case.

let MakeUpper(arr : string array) =
    for i in 0 .. arr.Length - 1 do
        Array.set arr i (arr.[i].ToUpper())
        printfn "%s"  arr.[i]

In visual studio select the function and run it in F# interactive.

Output –

> MakeUpper [|"Apple"; "Orange"; "Grapes"|] ;;

APPLE

ORANGE

GRAPES

With variant of for loop (foreach alike)

let PrintUpper(arr : string array) =
    for (fruit) in arr do
        printfn "%s"  (fruit.ToUpper())

 

Output –

> PrintUpper [|"Apple"; "Orange"; "Grapes"|] ;;

APPLE

ORANGE

GRAPES

So now we are pretty much good to start with playing around array. Let’s try to solve few problems using array to get up to speed. As I discussed before we’ll be solving the finding prime number problem using Sieve of Eratosthenes. Here’s a function to which is based on theory given at source:

// print prime number in a series up to n 
let PrimeSeive(n : int) = 
    let sequence = [|1..n|]
    let isPrime = Array.create n true
    let maxSquareRoot : int = System.Convert.ToInt32(System.Math.Sqrt(float n))
    let candidate = 2;
    
    for i in candidate..maxSquareRoot do
        if isPrime.[i] then
            let mutable j = i * i
            while j < n - 1 do
                isPrime.[j] <- false
                j <- j + i
 
        
    for index in 0..n - 1 do
        if isPrime.[index] then
            printf "%d, " index

 

Output –

> PrimeSeive 100 ;;

0, 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 99, val it : unit = ()

Here’s the equivalent code in CSharp(C#)

public static void PrimeSeive(int n)

{

    bool[] isPrime = new bool[n + 1];

    int maxSquareRoot = (int)Math.Sqrt(n);

 

    int candidate = 2;

 

    // Additional loop to initialize the bool array with default value

    for (int ind = 0; ind < isPrime.Length; ind++)

    {

        isPrime[ind] = true;

    }

 

    for (int i = candidate; i < Math.Sqrt(n); i += 1)

    {

        if (isPrime[i])

        for (int j = i * i; j < n; j = j += i)

        {

            isPrime[j] = false;

        }

    }

 

    for (int k = 0; k < n; k++)

    {

        if(isPrime[k])

        Console.WriteLine(k);

    }

}

Although the given solution in F# is not the best and not recommended because we’re using much of mutable types like any other imperative language. I’m not sure you readers have notices but look at the F# snippet how beautiful it does look without any block defining braces. In next post we’ll solve the same problem with immutable types and without using mutable.

Here’s few exercises for you:

What would be the output of below code?

// Guess the output, Write your answer in the comments.
let guessOutput = 
        for i in [|9..7..30|] do
         printfn "%d" i

Happy Learning!!!!

No comments:

Post a Comment