Arrays
Arrays
Foundations of Arrays
Introduction
An array is a list of values where:
Creating an Array
An array is created using the [| and the |] operators. You have many options. To create an array of specifically known values, the formula to follow is:
[| member-1; member-2; Member-n |]
With this formula, inside the operators, specify the value of each item. The items are separated by semicolons. Here is an example:
[| "James"; "Annette"; "Hughs"; "Daniel" "Martine" |]
The array members don't have to be on the same line; you can put them on different lines:
[| "James"; "Annette"; "Hughs"; "Daniel" "Martine" |]
If you do this, you can omit the semicolon. Also, to make your code easy to read, you should indent the items (but this is not a requirement):
[| "James" "Annette" "Hughs" "Daniel" "Martine" |]
If your array consists of consecutive ASCII characters, consecutive alphabetical letters, or incrementing numbers, you can specify its values as a range. In this case, inside the operators, the formula to follow is:
start-value .. end-value
Here is an example:
[| 'e' .. 'l' |]
If your array consists of consecutive numbers that follow a common skipping scheme, you can specify its values using a skip range. To do this, inside the operators, the formula to follow is:
Start .. Step .. End
Here is an example:
[| 0 .. 2 .. 20 |]
In the same way, if the array contains items whose letters or numbers will be based on a specific expression, you can use a for loop to create the value of each. To do that, inside the operators, the formula to follow is:
for variable-name in range -> body
Here is an example:
[| for number in 1 .. 10 -> number * number |]
An alternative to the -> operator is to use the do yield expression. Here is an example:
[| for number in 1 .. 10 do yield number * number * number |]
Naming an Array
To refer to an array as one, you can store it in a variable. This is done using the let keyword followed by a name for the variable, and assigned the array. Here are examples:
let names = [| "James"; "Annette"; "Hughs"; "Daniel"; "Martine" |] let letters = [| 'e' .. 'l' |] let evenNumbers = [| 0 .. 2 .. 20 |] let squared = [| for number in 1 .. 10 do yield number * number |]
Displaying an Array
To display an array and all its members in the printf() or the printfn() function, use %A. Here are examples:
printfn "Names: %A" ( [| "James"; "Annette"; "Hughs"; "Daniel"; "Martine" |] ); printfn "Letters: %A" ( [| 'e' .. 'l' |] ) printfn "Even Numbers: %A" ( [| 0 .. 2 .. 20 |] ) printfn "Squared Numbers: %A" ( [| for number in 1 .. 10 -> number * number * number |] )
These would produce:
Names: [|"James"; "Annette"; "Hughs"; "Daniel" "Martine"|] Letters: [|'e'; 'f'; 'g'; 'h'; 'i'; 'j'; 'k'; 'l'|] Even Numbers: [|0; 2; 4; 6; 8; 10; 12; 14; 16; 18; 20|] Squared Numbers: [|1; 8; 27; 64; 125; 216; 343; 512; 729; 1000|] Press any key to close this window . . .
In the same way, you can use the name of the variable that holds an array. Here are examples:
let names = [| "James"; "Annette"; "Hughs"; "Daniel"; "Martine" |] let letters = [| 'e' .. 'l' |] let evenNumbers = [| 0 .. 2 .. 20 |] let squared = [| for number in 1 .. 10 do yield number * number * number |] printfn "Names: %A" names; printfn "Letters: %A" letters; printfn "Even Numbers: %A" evenNumbers; printfn "Squared Numbers: %A\n" squared;
When you create an array, the compiler infers the type of values the array contains. In some cases, you will want to use a type other than the one the compiler thinks you are using. In some other cases, you will want to explicitly indicate the type of values of the array members.
To specify the data type of an array, after the name of the variable, type : followed the data type and the array keyword. Here are examples:
let names : string array = [| "James"; "Annette"; "Hughs"; "Daniel"; "Martine" |] let letters : char array = [| 'a' .. 'f' |] let oddNumbers : int array = [| 1 .. 2 .. 21 |] let squared : float array = [| for number in 1.00 .. 5.00 do yield ((-1.00) ** (number + 1.00)) / (2.00 * number) |] printfn "Names: %A" names; printfn "Letters: %A" letters; printfn "Odd Numbers: %A" oddNumbers; printfn "Squared Numbers: %A\n" squared;
This would produce:
Names: [|"James"; "Annette"; "Hughs"; "Daniel"; "Martine"|] Letters: [|'a'; 'b'; 'c'; 'd'; 'e'; 'f'|] Odd Numbers: [|1; 3; 5; 7; 9; 11; 13; 15; 17; 19; 21|] Squared Numbers: [|0.5; -0.25; 0.1666666667; -0.125; 0.1|] Press any key to close this window . . .
If the members consist of complex values, they are considered strings. In this case, you can omit the data type or set it as string. Here is an example:
let series = [| for number in 1 .. 8 do yield (string (1.00 ** (float number + 1.00)) + "/" + string (2 * number)) |] printfn "Series Array: %A\n" series;
This would produce:
Series Array: [|"1/2"; "1/4"; "1/6"; "1/8"; "1/10"; "1/12"; "1/14"; "1/16"|] Press any key to close this window . . .
Accessing the Members of an Array
Accessing Each Item
To access each individual item in an array, you can use a for loop. The formula to follow is:
for identifier in array Or array-name do body
Since all items are of the same type, use the appropriate character in the placeholder of the printf() or the printfn() function. Here is an example:
for n in [| "James"; "Annette"; "Hughs"; "Daniel"; "Martine" |] do printfn "Name: %s" n;
This would produce:
Name: James Name: Annette Name: Hughs Name: Daniel Name: Martine Press any key to close this window . . .
Accessing An Item by its Index
As mentioned in the begining, each member of an array occupies a specific position know as its index. The first item has an index of 0, the second has an index of 1, the third as an index of 2, and so on. To access an item, you apply the square brackets to the name of the array. The formula to go from the begining to the end of the array is:
for identifier = start to end do body
In the body of the loop, access each looping item using the following formula:
array-name.[identifier]
Based on the earlier description, if you have an array named courses and it has 6 items, to access the third, you would use courses.[4]. Here are examples:
let courses = [| "ASTR 100"; "WRTG 381"; "BEHS 220"; "PHIL 140"; "ACCT 302"; "MATH 241" |]; let cubedNumbers = [| for number in 1 .. 10 -> number * number * number |]; printfn "Course Code\tCredits"; for i = 0 to 5 do printfn "%s\t 3" courses.[i]; printfn "-----------------------------"; for i = 0 to 9 do printfn "Number: %d" cubedNumbers.[i];
This would produce:
Course Code Credits ASTR 100 3 WRTG 381 3 BEHS 220 3 PHIL 140 3 ACCT 302 3 MATH 241 3 ----------------------------- Number: 1 Number: 8 Number: 27 Number: 64 Number: 125 Number: 216 Number: 343 Number: 512 Number: 729 Number: 1000 Press any key to close this window . . .
Accessing the Members in a Range
You can consider that an array is a series of ranges of values, from the begining of the array to a certain item, from a certain item to another in a range, and from a certain item to the end. This means that, when it comes to ranges in the array, you have three options.
To access the range of items from the begining to a specific index, the formula to follow is:
array-name.[..Index]
Here is an example:
let courses = [| "WRTG 101";
"WRTG 102";
"WRTG 201";
"WRTG 288";
"WRTG 351";
"WRTG 381";
"WRTG 388";
"WRTG 390";
"WRTG 461" |];
printfn "All Courses =-----------------";
printfn "Course Code\tCredits";
for i = 0 to 7 do
printfn "%s\t 3" courses.[i];
printfn "-----------------------------";
printfn "First Four Courses =---------";
printfn "Course Code\tCredits";
let first = courses.[ .. 3 ]
for n in first do
printfn "%s\t 3" n;
This would produce:
All Courses =----------------- Course Code Credits WRTG 101 3 WRTG 102 3 WRTG 201 3 WRTG 288 3 WRTG 351 3 WRTG 381 3 WRTG 388 3 WRTG 390 3 ----------------------------- First Four Courses =--------- Course Code Credits WRTG 101 3 WRTG 102 3 WRTG 201 3 WRTG 288 3 Press any key to close this window . . .
To access the items in a certain range, specify the starting index, two periods, and the ending index. The formula to follow is:
array-name.[StartIndex .. EndIndex]
Here are examples:
let courses = [| "WRTG 101";
"WRTG 102";
"WRTG 201";
"WRTG 288";
"WRTG 351";
"WRTG 381";
"WRTG 388";
"WRTG 390";
"WRTG 461" |];
printfn "Some Courses =---------";
printfn "Course Code\tCredits";
let second = courses.[ 2 .. 4 ]
for n in second do
printfn "%s\t 3" n;
This would produce:
Some Courses =--------- Course Code Credits WRTG 201 3 WRTG 288 3 WRTG 351 3 Press any key to close this window . . .
To access some items at the end of the array, inside the [| and the |] operators, specify the starting index and add two periods. The formula to follow is:
array-name.[StartIndex .. ]
Here are examples:
let courses = [| "WRTG 101";
"WRTG 102";
"WRTG 201";
"WRTG 288";
"WRTG 351";
"WRTG 381";
"WRTG 388";
"WRTG 390";
"WRTG 461" |];
printfn "Last Courses =---------";
printfn "Course Code\tCredits";
for n in courses.[ 3 .. ] do
printfn "%s\t 3" n;
This would produce:
Last Courses =--------- Course Code Credits WRTG 288 3 WRTG 351 3 WRTG 381 3 WRTG 388 3 WRTG 390 3 WRTG 461 3
The Values of Items in an Array
An Empty Array
An array is considered empty if it doesn't contain any value. To create such an array, specify its value as [||]. To store that array in a variable, assign [||] to the variable. Here is an example:
let timesWorked = [||]
Even though the array is empty, you can access it. Here is an example:
let timesWorked = [||] printfn "Times Worked: %A" timesWorked
This would produce:
Times Worked: [||] Press any key to close this window . . .
Remember that an array is a list whose values must be specified at creation time. The reason is that the compiler needs to know the number of items in the array, and that number cannot change (that's the actual definition of an array as it is used in programming languages; in reality, the .NET Framework, or rather its Array class, provides a mechanism to change the size of an array). Based on this, if you create an empty array, it remains empty; as a result, you cannot add items to it (in reality, based on the real definitions of an array, you cannot add a new item to an array, but you can change the value that an existing item holds).
Checking Whether an Array is Empty
We know how to create an empty array, by leaving [||] empty. To let you find out whether an array is empty, you can use the match operator with an option as [||]. When that option is valid, the array is empty. You can use the underscore for the other option that indicates that the array has at least one element. Here are examples:
let numbers = [||] let names = [| "Frank"; "James"; "Joshua"; "Mary" |] match numbers with | [||] -> printfn "The array contains no element" | _ -> printfn "Numbers: %A" numbers match names with | [||] -> printfn "There are no names in the array" | _ -> printfn "Name: %A" names
This would produce:
The array contains no element Name: [|"Frank"; "James"; "Joshua"; "Mary"|] Press any key to close this window . . .
Setting the Values of Items
As mentioned already, when creating an array, you must provide the values of its items. Sometimes you don't have those values, maybe because they are not yet available. One solution is to provide sample values. The idea is to specify the number of items in the array. Here is an example:
let timesWorked = [| 0.00; 0.00; 0.00; 0.00; 0.00; 0.00; 0.00; |] printfn "Times Worked: %A" timesWorked
This would produce:
Times Worked: [|0.0; 0.0; 0.0; 0.0; 0.0; 0.0; 0.0|] Press any key to close this window . . .
Of course, the sample values depend on the type of values. Here is an example for string items:
let daysWorked = [| ""; ""; ""; ""; ""; ""; ""; |]
When you have done this, the compiler reserves a fixed area of the computer memory for the array and stores each item in the appropriate consecutive position. By definition, you cannot add new items to the array, but you can change the value stored in a certain position. To do this, access the item by its position using the .[] operator as we saw already. You can then assign the desired value using the mutable operator <-. Here are examples:
let timesWorked = [| 0.00; 0.00; 0.00; 0.00; 0.00; 0.00; 0.00; |]
let daysWorked = [| ""; ""; ""; ""; ""; ""; ""; |]
timesWorked.[0] <- 6.00
timesWorked.[1] <- 7.50
timesWorked.[2] <- 8.00
timesWorked.[3] <- 6.50
timesWorked.[4] <- 7.50
timesWorked.[5] <- 0.00
timesWorked.[6] <- 0.00
daysWorked.[0] <- "Monday"
daysWorked.[1] <- "Tuesday"
daysWorked.[2] <- "Wednesday"
daysWorked.[3] <- "Thursday"
daysWorked.[4] <- "Frisday"
daysWorked.[5] <- "Saturday"
daysWorked.[6] <- "Sunday"
printfn "Days Worked: "
for day in daysWorked do
printfn "\t%s" day
printfn "Times Worked: %A" timesWorked
This would produce:
Days Worked: Monday Tuesday Wednesday Thursday Frisday Saturday Sunday Times Worked: [|6.0; 7.5; 8.0; 6.5; 7.5; 0.0; 0.0|] Press any key to close this window . . .
Arrays and Functions
Returning an Array
You can create a function that manipulates some values, produces an array, and returns it. You can then call the function to get its returned array and use it as you see fit. Here is an example:
let daysWorked() = let daysWorked = [| ""; ""; ""; ""; ""; ""; ""; |] daysWorked.[0] <- "Monday "; daysWorked.[1] <- "Tuesday "; daysWorked.[2] <- "Wednesday"; daysWorked.[3] <- "Thursday "; daysWorked.[4] <- "Frisday "; daysWorked.[5] <- "Saturday "; daysWorked.[6] <- "Sunday "; // Array returned daysWorked let days = daysWorked(); printfn "=====================================" printfn "Day Worked\tTime Worked" printfn "-------------------------------------" for i = 0 to 6 do printfn "%s" days.[i]; printfn "====================================="
In the same way, you can pass one or more values to a function. The function can use the values to generate an array from its internal calculations. Here is an example:
let generateReciprocalInverses start finish =
[| for n = start to finish - 1 do yield "-1/" + (string n) |] // Returned array
let inverses = generateReciprocalInverses 3 12
let mutable i = 3;
printfn "================================="
printfn "Receiprocal Inverses from 3 to 12"
printfn "------------------------"
printfn " Reciprocal"
printfn "Nbr Inverse"
printfn "---------------------------------"
for n in inverses do
printfn "%i\t%s" i n
i <- i + 1
printfn "================================="
This would produce:
======================== Inverses from 3 to 12 ------------------------ Reciprocal Nbr Inverse ------------------------ 3 -1/3 4 -1/4 5 -1/5 6 -1/6 7 -1/7 8 -1/8 9 -1/9 10 -1/10 11 -1/11 ======================== Press any key to close this window . . .
An Array as Parameter
An array can be passed as a parameter to a function. Consider the following example:
let showPayroll values = for time in values do printfn "Time Worked: %0.02F" time;
When calling the function, pass an array that holds the appropriate and desired values. Here is an example:
let timesWorked = [| 8.00; 8.50; 6.50; 7.50; 9.00; 0.00; 0.00; |];
let showPayroll values =
for time in values do
printfn "Time Worked: %0.02F" time;
showPayroll timesWorked;
This would produce:
Time Worked: 8.00 Time Worked: 8.50 Time Worked: 6.50 Time Worked: 7.50 Time Worked: 9.00 Time Worked: 0.00 Time Worked: 0.00 Press any key to close this window . . .
In the samy way, you can pass more than one array to a function.
Remember that F# is an inferred language. This means that when passing an array or many arrays to a function, the compiler may not know the type of value an array parameter holds. The parameter can be anything. If the compiler has any difficult figuring out the types of parameter, it would produce an error. Therefore, it is recommended that it indicate the type of the parameter. Here are examples:
let timesWorked = [| 0.00; 0.00; 0.00; 0.00; 0.00; 0.00; 0.00; |]
let daysWorked = [| ""; ""; ""; ""; ""; ""; ""; |]
timesWorked.[0] <- 6.00
timesWorked.[1] <- 7.50
timesWorked.[2] <- 8.00
timesWorked.[3] <- 6.50
timesWorked.[4] <- 7.50
timesWorked.[5] <- 0.00
timesWorked.[6] <- 0.00
daysWorked.[0] <- "Monday ";
daysWorked.[1] <- "Tuesday ";
daysWorked.[2] <- "Wednesday";
daysWorked.[3] <- "Thursday ";
daysWorked.[4] <- "Frisday ";
daysWorked.[5] <- "Saturday ";
daysWorked.[6] <- "Sunday "
let showPayroll (days : string array) (values : float array) =
printfn "============================"
printfn "Day Worked\tTime Worked"
printfn "----------------------------"
for i = 0 to 6 do
printfn "%s\t%0.02F" days.[i] values.[i];
printfn "============================"
showPayroll daysWorked timesWorked;
This would produce:
============================ Day Worked Time Worked ---------------------------- Monday 6.00 Tuesday 7.50 Wednesday 8.00 Thursday 6.50 Frisday 7.50 Saturday 0.00 Sunday 0.00 ============================ Press any key to close this window . . .
A function can do more than simply displaying the values of an array it gets as parameter. It can use the values of that array, perform some calculations, and simply return a new value. A function can also get an array as parameter and return an array.
Arrays and Records
An Array of Records
The items of an array can come from a record. Of course, you must have a record. You can create various objects and add each to an array. Here is an example:
type Employee = {
EmployeeNumber : string
FirstName : string
LastName : string
HourlySalary : double }
let empl80223840 = { EmployeeNumber = "8022-3840"; FirstName = "Mark"; LastName = "Plant"; HourlySalary = 24.55 }
let empl58402497 = { EmployeeNumber = "5840-2497"; FirstName = "Carol"; LastName = "Mylans"; HourlySalary = 16.25 }
let empl20817008 = { EmployeeNumber = "2081-7008"; FirstName = "Maria"; LastName = "Pappas"; HourlySalary = 22.75 }
let employees = [| empl80223840; empl58402497; empl20817008 |]
A better alternative is to create each object directly in the array. After creating the array, you can access the members of the record using the period operator. Here is an example:
type Employee = {
EmployeeNumber : string
FirstName : string
LastName : string
HourlySalary : double }
let employees = [| { EmployeeNumber = "8022-3840"; FirstName = "Mark"; LastName = "Plant"; HourlySalary = 24.55 };
{ EmployeeNumber = "5840-2497"; FirstName = "Carol"; LastName = "Mylans"; HourlySalary = 16.25 };
{ EmployeeNumber = "2081-7008"; FirstName = "Maria"; LastName = "Pappas"; HourlySalary = 22.75 }; |]
printfn "Employees Records _______"
for empl in employees do
printfn "=-=-=-=-=-=-=-=-=-=-=-=-="
printfn "Employee Record"
printfn "-------------------------"
printfn "Employee #: %s" empl.EmployeeNumber
printfn "First Name: %s" empl.FirstName
printfn "Last Name: %s" empl.LastName
printfn "Hourly Salary: %.02F" empl.HourlySalary
printfn "=============================================="
This would produce:
Employees Records _______ =-=-=-=-=-=-=-=-=-=-=-=-= Employee Record ------------------------- Employee #: 8022-3840 First Name: Mark Last Name: Plant Hourly Salary: 24.55 =-=-=-=-=-=-=-=-=-=-=-=-= Employee Record ------------------------- Employee #: 5840-2497 First Name: Carol Last Name: Mylans Hourly Salary: 16.25 =-=-=-=-=-=-=-=-=-=-=-=-= Employee Record ------------------------- Employee #: 2081-7008 First Name: Maria Last Name: Pappas Hourly Salary: 22.75 ============================================== Press any key to close this window . . .
An Array as a Member of a Record
A member of a record can be an array. When creating the member, specify its type followed by the array keyword. Here is an example:
type RoadSystem = {
RoadName : string
Distance : float
Location : string
Intersections : string array }
In the same way, you can create as many array members as you want. When creating an object, specify the value of the member as an array. Outside the object, you can display the array member using %A in the placeholder of the printf() or the printfn() function. Here is an example:
type RoadType = | Court | Street | Road | Avenue | Boulevard | StateRoad | StateHighway | Interstate | Unknown type RoadSystem = { RoadName : string Category : RoadType Distance : float Location : string Intersections : string array } let MD410 = { RoadName = "MD 410"; Category = RoadType.Road; Distance = 13.92; // mi => 22.40 km Location = "From East Bethesda to Pennsy Drive in Landover Hills"; Intersections = [| "MD 355"; "MD 187"; "Maple Ave"; "MD 185"; "Colesville Rd" |] } printfn "Road System Database" printfn "=-----------------------------------------------------------------------------=" printfn "Road Name: %s" MD410.RoadName printfn "Category: %A" MD410.Category printfn "Distance: %0.2f miles" MD410.Distance printfn "Location: %s" MD410.Location printfn "Intersects With: %A\n" MD410.Intersections printfn "=-----------------------------------------------------------------------------="
This would produce:
Road System Database =-----------------------------------------------------------------------------= Road Name: MD 410 Category: Road Distance: 13.92 miles Location: From East Bethesda to Pennsy Drive in Landover Hills Intersects With: [|"MD 355"; "MD 187"; "Maple Ave"; "MD 185"; "Colesville Rd"|] =-----------------------------------------------------------------------------= Press any key to close this window . . .
Arrays and Classes
An Array of Objects
The members of an array can be of any type, including objects of a class or structure. You can first create each object and add it to an array variable. Here is an example:
type StoreItem(number, make, category, subcategory, name, size, price, discrate) =
let mutable nbr = number
let mutable mk = make
let mutable cat = category
let mutable sub = subcategory
let mutable nm = name
let mutable sz = size
let mutable prc = price
let mutable rate = discrate
member this.ItemNumber with get() = nbr and set(value) = nbr <- value;
member this.Manufacturer with get() = mk and set(value) = mk <- value;
member this.Category with get() = cat and set(value) = cat <- value;
member this.SubCategory with get() = sub and set(value) = sub <- value;
member this.ItemName with get() = nm and set(value) = nm <- value;
member this.ItemSize with get() = sz and set(value) = sz <- value;
member this.UnitPrice with get() = prc and set(value) = prc <- value;
member this.DiscountRate with get() = rate and set(value) = rate <- value;
member this.GetDiscountAmount() = this.UnitPrice * this.DiscountRate / 100.00;
member this.MarkedPrice() = this.UnitPrice - this.DiscountRate;
new(number, make, category, subcategory, name, size, price) = StoreItem(number, make, category, subcategory, name, size, price, 0.00)
let si1 = StoreItem("441180", "Ralph Lauren", "Girls", "Shirts", "Girls 2-6X Short-Sleeved Mesh Polo Shirt", "3/3T", 34.95);
let si2 = StoreItem("292915", "Kenneth Cole", "Women", "Dresses", "Three-Quarter Sleeved Dress", "L", 145.50, 20.00);
let si3 = StoreItem("479160", "Polo Ralph Lauren", "Men", "Pants", "Classic Straight-Leg Jeans", "33W - 32L", 84.85);
let storeItems = [| si1; si2; si3;|];
A better alternative is to create each object in its placeholder in the array. Here is an example:
let storeItems = [| StoreItem("441180", "Ralph Lauren", "Girls", "Shirts", "Girls 2-6X Short-Sleeved Mesh Polo Shirt", "3/3T", 34.95); StoreItem("292915", "Kenneth Cole", "Women", "Dresses", "Three-Quarter Sleeved Dress", "L", 145.50, 20.00); StoreItem("479160", "Polo Ralph Lauren", "Men", "Pants", "Classic Straight-Leg Jeans", "33W - 32L", 84.85); |];
To access a member of the array, you can use a for loop. Then, from the name of the looping identifier, use the period operator to access a member of the class. Here are examples:
type StoreItem(number, make, category, subcategory, name, size, price, discrate) = let mutable nbr = number let mutable mk = make let mutable cat = category let mutable sub = subcategory let mutable nm = name let mutable sz = size let mutable prc = price let mutable rate = discrate member this.ItemNumber with get() = nbr and set(value) = nbr <- value; member this.Manufacturer with get() = mk and set(value) = mk <- value; member this.Category with get() = cat and set(value) = cat <- value; member this.SubCategory with get() = sub and set(value) = sub <- value; member this.ItemName with get() = nm and set(value) = nm <- value; member this.ItemSize with get() = sz and set(value) = sz <- value; member this.UnitPrice with get() = prc and set(value) = prc <- value; member this.DiscountRate with get() = rate and set(value) = rate <- value; member this.GetDiscountAmount() = this.UnitPrice * this.DiscountRate / 100.00; member this.MarkedPrice() = this.UnitPrice - this.GetDiscountAmount(); new(number, make, category, subcategory, name, size, price) = StoreItem(number, make, category, subcategory, name, size, price, 0.00) let storeItems = [| StoreItem("441180", "Ralph Lauren", "Girls", "Shirts", "Girls 2-6X Short-Sleeved Mesh Polo Shirt", "3/3T", 34.95); StoreItem("292915", "Kenneth Cole", "Women", "Dresses", "Three-Quarter Sleeved Dress", "L", 145.50, 20.00); StoreItem("479160", "Polo Ralph Lauren", "Men", "Pants", "Classic Straight-Leg Jeans", "33W - 32L", 84.85); StoreItem("561150", "Kenneth Cole", "Women", "Dresses", "Three-Quarter Sleeved Dress", "XS", 145.50, 20.00); StoreItem("689771", "Calvin Klein", "Men", "Pants", "Straight Leg Jean in Black Wash", "38/30", 45.00); StoreItem("570810", "Nautica", "Boys", "Sweaters", "Boys 2-7 Cashmere Cable V-neck Sweater", "2T/3T", 145.00); |]; printfn "________________ Store Items _______________________________" printfn "============================================================" for storeItem in storeItems do printfn "Item #: %s" storeItem.ItemNumber; printfn "Manufacturer: %s" storeItem.Manufacturer; printfn "Category: %s" storeItem.Category; printfn "Sub-Category: %s" storeItem.SubCategory; printfn "Item Name: %s" storeItem.ItemName; printfn "Item Size: %s" storeItem.ItemSize; printfn "Unit Price: %0.02f" storeItem.UnitPrice; printfn "Discount Rate: %0.0f%s" storeItem.DiscountRate "%"; printfn "Discount Amount: %0.02f" (storeItem.GetDiscountAmount()); printfn "Marked Price: %0.02f" (storeItem.MarkedPrice()); printfn "------------------------------------------------------------"
This would produce:
________________ Store Items _______________________________ ============================================================ Item #: 441180 Manufacturer: Ralph Lauren Category: Girls Sub-Category: Shirts Item Name: Girls 2-6X Short-Sleeved Mesh Polo Shirt Item Size: 3/3T Unit Price: 34.95 Discount Rate: 0% Discount Amount: 0.00 Marked Price: 34.95 ------------------------------------------------------------ Item #: 292915 Manufacturer: Kenneth Cole Category: Women Sub-Category: Dresses Item Name: Three-Quarter Sleeved Dress Item Size: L Unit Price: 145.50 Discount Rate: 20% Discount Amount: 29.10 Marked Price: 116.40 ------------------------------------------------------------ Item #: 479160 Manufacturer: Polo Ralph Lauren Category: Men Sub-Category: Pants Item Name: Classic Straight-Leg Jeans Item Size: 33W - 32L Unit Price: 84.85 Discount Rate: 0% Discount Amount: 0.00 Marked Price: 84.85 ------------------------------------------------------------ Item #: 561150 Manufacturer: Kenneth Cole Category: Women Sub-Category: Dresses Item Name: Three-Quarter Sleeved Dress Item Size: XS Unit Price: 145.50 Discount Rate: 20% Discount Amount: 29.10 Marked Price: 116.40 ------------------------------------------------------------ Item #: 689771 Manufacturer: Calvin Klein Category: Men Sub-Category: Pants Item Name: Straight Leg Jean in Black Wash Item Size: 38/30 Unit Price: 45.00 Discount Rate: 0% Discount Amount: 0.00 Marked Price: 45.00 ------------------------------------------------------------ Item #: 570810 Manufacturer: Nautica Category: Boys Sub-Category: Sweaters Item Name: Boys 2-7 Cashmere Cable V-neck Sweater Item Size: 2T/3T Unit Price: 145.00 Discount Rate: 0% Discount Amount: 0.00 Marked Price: 145.00 ------------------------------------------------------------ Press any key to close this window . . .
Arrays and Properties of a Class
We already know how to pass an array as parameter. This means that an array can be passed to the constructor of a class. On the other hand, a property of a class can be an array. In fact, you can create a read-only property that would only produce an array that clients of the class can use. Otherwise, you can create a read-write property that gets its value as array from the outside and makes its array value available to the outside world.
Normally, when creating a read-write property that would use an array, you simply create a regular property. Here is an example:
type PayrollPreparation(number, times) =
let mutable nbr = number;
let mutable tms = times;
member this.EmployeeeNumber with get() = nbr and set(value) = nbr <- value;
member this.TimesWorked with get() = tms and set(value) = tms <- value;
It is when you specify the value of the property that you provide the array. Once this is done, when using the property outside the class, treat it as an array. Here is an example:
type Employee = { EmployeeNumber : string FirstName : string LastName : string HourlySalary : double } let employees = [| { EmployeeNumber = "8022-3840"; FirstName = "Mark"; LastName = "Plant"; HourlySalary = 24.55 }; { EmployeeNumber = "5840-2497"; FirstName = "Carol"; LastName = "Mylans"; HourlySalary = 16.25 }; { EmployeeNumber = "2081-7008"; FirstName = "Maria"; LastName = "Pappas"; HourlySalary = 22.75 }; |] type PayrollPreparation(number, times) = let mutable nbr = number; let mutable tms = times; member this.EmployeeeNumber with get() = nbr and set(value) = nbr <- value; member this.TimesWorked with get() = tms and set(value) = tms <- value; member this.CalculateTotalTime() = let mutable sum = 0.00 for t in tms do sum <- sum + t sum member this.CalculateWeeklySalary() = let mutable salary = 0.00; for empl in employees do if empl.EmployeeNumber = nbr then salary <- empl.HourlySalary this.CalculateTotalTime() * salary let pp = PayrollPreparation("5840-2497", [| 6.0; 7.5; 8.0; 6.5; 7.5; 0.0; 0.0 |]); printfn "======================================================" printfn "Employee Payroll" printfn "------------------------------------------------------" printfn "Employee #: %s" pp.EmployeeeNumber; printf "Full Name: " do for empl in employees do if empl.EmployeeNumber = pp.EmployeeeNumber then printfn "%s, %s" empl.LastName empl.FirstName; printf "Hourly Salary: " do for empl in employees do if empl.EmployeeNumber = pp.EmployeeeNumber then printfn "%.02F" empl.HourlySalary; printfn "Times Worked: %A:" pp.TimesWorked; printfn "Weekly Time: %.02F" (pp.CalculateTotalTime()); printfn "Weekly Salary: %0.02f" (pp.CalculateWeeklySalary()); printfn "======================================================";
This would produce:
====================================================== Employee Payroll ------------------------------------------------------ Employee #: 5840-2497 Full Name: Mylans, Carol Hourly Salary: 16.25 Times Worked: [|6.0; 7.5; 8.0; 6.5; 7.5; 0.0; 0.0|]: Weekly Time: 35.50 Weekly Salary: 576.88 ====================================================== Press any key to close this window . . .
Arrays and Methods of a Class
Like a regular function in a module, a method of a class can use an array in many ways. For example, a method can receive an array as parameter. We saw this for a constructor. A method can also return an array. When accessing the method outside the class, remember that it returns an array. This means that you can apply the operations of arrays on the call to that method. Here is an example:
type Employee = { EmployeeNumber : string FirstName : string LastName : string HourlySalary : double } let employees = [| { EmployeeNumber = "8022-3840"; FirstName = "Mark"; LastName = "Plant"; HourlySalary = 24.55 }; { EmployeeNumber = "5840-2497"; FirstName = "Carol"; LastName = "Mylans"; HourlySalary = 16.25 }; { EmployeeNumber = "2081-7008"; FirstName = "Maria"; LastName = "Pappas"; HourlySalary = 22.75 }; |] type PayrollPreparation(number, times) = let mutable nbr = number; let mutable tms = times; member this.EmployeeeNumber with get() = nbr and set(value) = nbr <- value; member this.TimesWorked with get() = tms and set(value) = tms <- value; member this.PaySummary(hourlySalary) : float array = let mutable regularTime = 0.00 let mutable overtime = 0.00 let mutable regularAmount = 0.00 let mutable overtimeSalary = 0.00 let mutable totalWeekTime = 0.00 let mutable overtimeAmount = 0.00 for t in tms do totalWeekTime <- totalWeekTime + t overtimeSalary <- hourlySalary * 1.5 // If the employee worked under 40 hours, there is no overtime if totalWeekTime < 40. then regularTime <- totalWeekTime regularAmount <- hourlySalary * regularTime //overtime <- 0.00 //overtimeAmount <- 0.00 // If the employee worked over 40 hours, calculate the overtime elif totalWeekTime >= 40. then regularTime <- 40. regularAmount <- hourlySalary * 40. overtime <- totalWeekTime - 40. overtimeAmount <- overtime * overtimeSalary [| regularTime; overtime; regularAmount; overtimeAmount; regularAmount + overtimeAmount |] let pp = PayrollPreparation("5840-2497", [| 6.0; 7.5; 8.0; 6.5; 7.5; 0.0; 0.0 |]); //let pp = PayrollPreparation("8022-3840", [| 8.50; 9.50; 10.00; 8.50; 9.50; 0.0; 0.0 |]); let mutable salary = 0.00 do for empl in employees do if empl.EmployeeNumber = pp.EmployeeeNumber then salary <- empl.HourlySalary; printfn "======================================" printfn "Employee Payroll" printfn "--------------------------------------" printfn "Employee #:\t\t\t%s" pp.EmployeeeNumber; printf "Full Name:\t\t\t" do for empl in employees do if empl.EmployeeNumber = pp.EmployeeeNumber then printfn "%s, %s" empl.LastName empl.FirstName; printfn "Hourly Salary:\t\t%.02F" salary; printfn "Pay Summary___________________________" for i = 0 to 4 do printfn "%s\t%0.02f" [| "Regular Time: "; "Overtime: "; "Regular Amount: "; "Overtime Salary:"; "Net Pay: " |].[i] (pp.PaySummary(salary)).[i] printfn "--------------------------------------"
This would produce:
====================================== Employee Payroll -------------------------------------- Employee #: 5840-2497 Full Name: Mylans, Carol Hourly Salary: 16.25 Pay Summary___________________________ Regular Time: 35.50 -------------------------------------- Overtime: 0.00 -------------------------------------- Regular Amount: 576.88 -------------------------------------- Overtime Salary: 0.00 -------------------------------------- Net Pay: 576.88 --------------------------------------
Notice that the method could have been written as follows (it may be long to read but it produces the same result):
type PayrollPreparation(number, times) =
let mutable nbr = number;
let mutable tms = times;
member this.EmployeeeNumber with get() = nbr and set(value) = nbr <- value;
member this.TimesWorked with get() = tms and set(value) = tms <- value;
member this.PaySummary(hourlySalary) : float array =
let mutable totalWeekTime = 0.00
for t in tms do totalWeekTime <- totalWeekTime + t
// If the employee worked under 40 hours, there is no overtime
if totalWeekTime < 40. then
[| totalWeekTime; 0.00; hourlySalary * totalWeekTime; 0.00; hourlySalary * totalWeekTime |]
else // if totalWeekTime >= 40. then
[| 40.00; totalWeekTime - 40.00; hourlySalary * 40.00; (totalWeekTime - 40.00) * (hourlySalary * 1.50); hourlySalary * 40.00 + ((totalWeekTime - 40.00) * (hourlySalary * 1.50)) |]
Characteristics of Arrays
Introduction
The F# language higly supports arrays. It provides many mechanisms to perform various types of operations. Besides the regular core operations of the language, the language's own library is equipped with a namespace named Microsoft.FSharp.Collections in which exists a module named Array(https://github.com/dotnet/fsharp/blob/main/src/FSharp.Core/array.fs).
An Empty Array
In some cases, if you are not ready to specify the values when creating the array, you can create it empty. To do this, specify the value of the array as [||]. Here is an example:
let timesWorked = [||];
printfn "Times Worked: %A" timesWorked;
This would produce:
Times Worked: [||] Press any key to close this window . . .
As an alternative, to let you create an empty array, the Array module provides a function named empty. Its signature is:
Array.empty<'T> : 'T []
Here is an example of using it:
let timesWorked = Array.empty;
printfn "Times Worked: %A" timesWorked;
To let you find out whether an array is empty, the Array module provides a function named isEmpty. Its signature is:
Array.isEmpty : 'T [] -> bool
The Length of an Array
The length of an array is the number of items it contains. To let you get this information, the Array module is equipped with a property named Length. Here is an example of using it:
type Employee = {
EmployeeNumber : string
FirstName : string
LastName : string
HourlySalary : double }
let employees = [| { EmployeeNumber = "8022-3840"; FirstName = "Mark"; LastName = "Plant"; HourlySalary = 24.55 };
{ EmployeeNumber = "5840-2497"; FirstName = "Carol"; LastName = "Mylans"; HourlySalary = 16.25 };
{ EmployeeNumber = "2081-7008"; FirstName = "Maria"; LastName = "Pappas"; HourlySalary = 22.75 }; |]
type PayrollPreparation(number, times) =
let mutable nbr = number;
let mutable tms = times;
member this.EmployeeeNumber with get() = nbr and set(value) = nbr <- value;
member this.TimesWorked with get() = tms and set(value) = tms <- value;
member this.PaySummary(hourlySalary) : float array =
let mutable regularTime = 0.00
let mutable overtime = 0.00
let mutable regularAmount = 0.00
let mutable overtimeSalary = 0.00
let mutable totalWeekTime = 0.00
let mutable overtimeAmount = 0.00
for t in tms do totalWeekTime <- totalWeekTime + t
overtimeSalary <- hourlySalary * 1.5
// If the employee worked under 40 hours, there is no overtime
if totalWeekTime < 40. then
regularTime <- totalWeekTime
regularAmount <- hourlySalary * regularTime
//overtime <- 0.00
//overtimeAmount <- 0.00
// If the employee worked over 40 hours, calculate the overtime
elif totalWeekTime >= 40. then
regularTime <- 40.
regularAmount <- hourlySalary * 40.
overtime <- totalWeekTime - 40.
overtimeAmount <- overtime * overtimeSalary
[| regularTime; overtime; regularAmount; overtimeAmount; regularAmount + overtimeAmount |]
member this.CalculateTotalTime() =
let mutable sum = 0.00
for t in tms do sum <- sum + t
sum
member this.CalculateWeeklySalary() =
let mutable salary = 0.00;
for empl in employees do
if empl.EmployeeNumber = nbr then salary <- empl.HourlySalary
this.CalculateTotalTime() * salary
let pp = PayrollPreparation("5840-2497", [| 6.0; 7.5; 8.0; 6.5; 7.5; 0.0; 0.0 |]);
//let pp = PayrollPreparation("8022-3840", [| 8.50; 9.50; 10.00; 8.50; 9.50; 0.0; 0.0 |]);
let mutable salary = 0.00
do
for empl in employees do
if empl.EmployeeNumber = pp.EmployeeeNumber then salary <- empl.HourlySalary;
printfn "======================================"
printfn "Employee Payroll"
printfn "--------------------------------------"
printfn "Employee #:\t\t\t%s" pp.EmployeeeNumber;
printf "Full Name:\t\t\t"
do
for empl in employees do
if empl.EmployeeNumber = pp.EmployeeeNumber then printfn "%s, %s" empl.LastName empl.FirstName;
printfn "Hourly Salary:\t\t%.02F" salary;
printfn "Pay Summary___________________________"
for i = 0 to (pp.PaySummary(salary)).Length - 1 do
printfn "%s\t%0.02f" [| "Regular Time: ";
"Overtime: ";
"Regular Amount: ";
"Overtime Salary:";
"Net Pay: " |].[i]
(pp.PaySummary(salary)).[i]
printfn "--------------------------------------"
As an alternative, the Array module is equipped with a function named length. The function takes one argument as the array whose number of items must be found.
Techniques of Creating Arrays
Creating an Array
We know that there are various techniques to create an array, and when creating an array, you should provide the original values of the array. One way to do this is is to initialize the array with the values of your choice. To support this, the Array module is equipped with a method named create. Its signature is:
Array.create : int -> 'T -> 'T []
This method takes two arguments. The first is the number of items the array will need. The second argument is the default value for each item.
Creating an Array With Zero Values
If you create an empty array, it remains empty and you cannot add values to it. That's why, when creating an array, you should provide the desired values. If you don't have those values, you can still create an array, specify its number of items, but specify each item as 0. To support this operation, the Array module is equipped with a method named zeroCreate. Its signature is:
Array.zeroCreate : int -> 'T []
This method takes one argument as the number of items in the array. Each item receives a value of 0. Here is an example of calling it:
let times : float array = Array.zeroCreate 5; printfn "Times Worked: %A" times;
This would produce:
Times Worked: [|0.0; 0.0; 0.0; 0.0; 0.0|] Press any key to close this window . . .
Initialyzing an Array
Introduction
After creating the array, you can specify the values of its members or you can change them. This can be done by accessing an item using the period operator and assigning a value using the -> operator. Here are exampes:
let times : float array = Array.zeroCreate 7;
times.[0] <- 8.00
times.[1] <- 8.50
times.[2] <- 6.00
times.[3] <- 9.00
times.[4] <- 7.50
times.[5] <- 9.00
times.[6] <- 7.50
for time in times do
printfn "Time Worked: %0.02F" time;
This would produce:
Time Worked: 8.00 Time Worked: 8.50 Time Worked: 6.00 Time Worked: 9.00 Time Worked: 7.50 Time Worked: 9.00 Time Worked: 7.50 Press any key to close this window . . .
If the members of the array are objects, you can access each item by its index and assign an object-value to it. Here are examples:
type OccupancyStatus =
| Other = 0
| Available = 1
| Occupied = 2
| NeedsRepair = 3
type Apartment = {
UnitNumber : string
Bedrooms : int
Bathrooms : float
SecurityDeposit : int
MonthlyRate : int
Status : OccupancyStatus }
let apartments = Array.create 5 { UnitNumber = "101"; Bedrooms = 2; Bathrooms = 2.00; SecurityDeposit = 650; MonthlyRate = 1150; Status = OccupancyStatus.Available };
apartments.[1] <- { UnitNumber = "102"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate = 950; Status = OccupancyStatus.NeedsRepair }
apartments.[2] <- { UnitNumber = "103"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate = 925; Status = OccupancyStatus.Available }
apartments.[3] <- { UnitNumber = "104"; Bedrooms = 3; Bathrooms = 2.00; SecurityDeposit = 850; MonthlyRate = 1350; Status = OccupancyStatus.Occupied }
apartments.[4] <- { UnitNumber = "105"; Bedrooms = 2; Bathrooms = 1.00; SecurityDeposit = 550; MonthlyRate = 1150; Status = OccupancyStatus.Available }
Setting the Values of an Array
To allow you to specify or change the value of an element of an array, the Array module provides a function named set. Its signature is:
Array.set : 'T [] -> int -> 'T -> unit
This function takes three arguments. The first is the array with elements. The second argument is the index of the element whose value you want to specify. The last argument is the value to set. Here is an example that sets the values of the second and the fourth members of the array:
type StoreItem(number, make, category, subcategory, name, size, price, discrate) =
let mutable nbr = number
let mutable mk = make
let mutable cat = category
let mutable sub = subcategory
let mutable nm = name
let mutable sz = size
let mutable prc = price
let mutable rate = discrate
member this.ItemNumber with get() = nbr and set(value) = nbr <- value;
member this.Manufacturer with get() = mk and set(value) = mk <- value;
member this.Category with get() = cat and set(value) = cat <- value;
member this.SubCategory with get() = sub and set(value) = sub <- value;
member this.ItemName with get() = nm and set(value) = nm <- value;
member this.ItemSize with get() = sz and set(value) = sz <- value;
member this.UnitPrice with get() = prc and set(value) = prc <- value;
member this.DiscountRate with get() = rate and set(value) = rate <- value;
member this.GetDiscountAmount() = this.UnitPrice * this.DiscountRate / 100.00;
member this.MarkedPrice() = this.UnitPrice - this.GetDiscountAmount();
new() = StoreItem("", "", "", "", "", "", 0.00, 0.00)
new(number, make, category, subcategory, name, size, price) = StoreItem(number, make, category, subcategory, name, size, price, 0.00)
let storeItems = [| new StoreItem(); new StoreItem(); new StoreItem(); new StoreItem(); new StoreItem(); |];
Array.set storeItems 1 (StoreItem("948596", "Tommy Hilfiger", "Men", "Shirts", "Texture Oxford Slim Fit Long Sleeve Dress Shirt", "17 34/35", 47.75))
Array.set storeItems 3 (StoreItem("497960", "Kenneth Cole Reaction", "Men", "Shirts", "Dress Shirt, Urban Satin", "16.5 36/37", 37.75))
printfn "Store Item: %A: " storeItems.[0]
printfn "________________ Store Items _______________________________"
printfn "============================================================"
for storeItem in storeItems do
printfn "Item #: %s" storeItem.ItemNumber;
printfn "Manufacturer: %s" storeItem.Manufacturer;
printfn "Category: %s" storeItem.Category;
printfn "Sub-Category: %s" storeItem.SubCategory;
printfn "Item Name: %s" storeItem.ItemName;
printfn "Item Size: %s" storeItem.ItemSize;
printfn "Unit Price: %0.02f" storeItem.UnitPrice;
printfn "Discount Rate: %0.0f%s" storeItem.DiscountRate "%";
printfn "Discount Amount: %0.02f" (storeItem.GetDiscountAmount());
printfn "Marked Price: %0.02f" (storeItem.MarkedPrice());
printfn "------------------------------------------------------------"
This would produce:
________________ Store Items _______________________________ ============================================================ Item #: Manufacturer: Category: Sub-Category: Item Name: Item Size: Unit Price: 0.00 Discount Rate: 0% Discount Amount: 0.00 Marked Price: 0.00 ------------------------------------------------------------ Item #: 948596 Manufacturer: Tommy Hilfiger Category: Men Sub-Category: Shirts Item Name: Texture Oxford Slim Fit Long Sleeve Dress Shirt Item Size: 17 34/35 Unit Price: 47.75 Discount Rate: 0% Discount Amount: 0.00 Marked Price: 47.75 ------------------------------------------------------------ Item #: Manufacturer: Category: Sub-Category: Item Name: Item Size: Unit Price: 0.00 Discount Rate: 0% Discount Amount: 0.00 Marked Price: 0.00 ------------------------------------------------------------ Item #: 497960 Manufacturer: Kenneth Cole Reaction Category: Men Sub-Category: Shirts Item Name: Dress Shirt, Urban Satin Item Size: 16.5 36/37 Unit Price: 37.75 Discount Rate: 0% Discount Amount: 0.00 Marked Price: 37.75 ------------------------------------------------------------ Item #: Manufacturer: Category: Sub-Category: Item Name: Item Size: Unit Price: 0.00 Discount Rate: 0% Discount Amount: 0.00 Marked Price: 0.00 ------------------------------------------------------------ Press any key to close this window . . .
Initialyzing an Array Using an Expression
Another way to create an array is to provide its values using an expression. To support this, the Array module provides a function named init. Its signature is:
Array.init : int -> (int -> 'T) -> 'T []
Here is an example:
let yCoords = Array.init 8 (fun a -> (2 * a) + 1);
printfn "Y Coordinates: %A" yCoords;
This would produce:
Y Coordinates: [|1; 3; 5; 7; 9; 11; 13; 15|] Press any key to close this window . . .
Copying a Fraction of an Array
You can get the fraction of an array and copy that fraction into another array. This operation can be carried by the blit() function of the Array module. Its signature is:
Array.blit : 'T [] -> int -> 'T [] -> int -> int -> unit
This method takes five arguments. The first argument is the array that holds the original value. It is called the source array. The third argument is the array that will receive the fraction. This is called the target array. The target can contain some or all values. This means that some values could have default or unnecessary values. The second argument is the starting index from which to copy values from the source array. The fourth argument is the starting index where to start adding the values that were copied from the source. The last (fifth) argument is the number of items to copy from the source, of course starting from the index specified by the second argument. Here is an example:
type StoreItem(number, make, category, subcategory, name, size, price, discrate) =
let mutable nbr = number
let mutable mk = make
let mutable cat = category
let mutable sub = subcategory
let mutable nm = name
let mutable sz = size
let mutable prc = price
let mutable rate = discrate
member this.ItemNumber with get() = nbr and set(value) = nbr <- value;
member this.Manufacturer with get() = mk and set(value) = mk <- value;
member this.Category with get() = cat and set(value) = cat <- value;
member this.SubCategory with get() = sub and set(value) = sub <- value;
member this.ItemName with get() = nm and set(value) = nm <- value;
member this.ItemSize with get() = sz and set(value) = sz <- value;
member this.UnitPrice with get() = prc and set(value) = prc <- value;
member this.DiscountRate with get() = rate and set(value) = rate <- value;
member this.GetDiscountAmount() = this.UnitPrice * this.DiscountRate / 100.00;
member this.MarkedPrice() = this.UnitPrice - this.GetDiscountAmount();
new() = StoreItem("", "", "", "", "", "", 0.00, 0.00)
new(number, make, category, subcategory, name, size, price) = StoreItem(number, make, category, subcategory, name, size, price, 0.00)
let storeItems = [| StoreItem("441180", "Ralph Lauren", "Girls", "Shirts", "Girls 2-6X Short-Sleeved Mesh Polo Shirt", "3/3T", 34.95);
StoreItem("292915", "Kenneth Cole", "Women", "Dresses", "Three-Quarter Sleeved Dress", "L", 145.50, 20.00);
StoreItem("479160", "Polo Ralph Lauren", "Men", "Pants", "Classic Straight-Leg Jeans", "33W - 32L", 84.85);
StoreItem("561150", "Kenneth Cole", "Women", "Dresses", "Three-Quarter Sleeved Dress", "XS", 145.50);
StoreItem("689771", "Calvin Klein", "Men", "Pants", "Straight Leg Jean in Black Wash", "38/30", 45.00, 25.00);
StoreItem("570810", "Nautica", "Boys", "Sweaters", "Boys 2-7 Cashmere Cable V-neck Sweater", "2T/3T", 145.00);
|];
// Here is a new array with empty values
let arrivals = [| StoreItem("428741", "Guess", "Girls", "Dresses", "Girls 2-6X Denim Print Ruffled Dress", "3T", 34.95, 35.00);
StoreItem(); StoreItem(); |]
// Copy the items from the third position (index = 2) of the storeItems (the source) array.
// Add them from the second position (index = 1) of the blitter array (the target).
// From the source array, copy 3 items
Array.blit storeItems 3 arrivals 1 2;
printfn "________________ Store Items _______________________________"
printfn "============================================================"
for storeItem in arrivals do
printfn "Item #: %s" storeItem.ItemNumber;
printfn "Manufacturer: %s" storeItem.Manufacturer;
printfn "Category: %s" storeItem.Category;
printfn "Sub-Category: %s" storeItem.SubCategory;
printfn "Item Name: %s" storeItem.ItemName;
printfn "Item Size: %s" storeItem.ItemSize;
printfn "Unit Price: %0.02f" storeItem.UnitPrice;
printfn "Discount Rate: %0.0f%s" storeItem.DiscountRate "%";
printfn "Discount Amount: %0.02f" (storeItem.GetDiscountAmount());
printfn "Marked Price: %0.02f" (storeItem.MarkedPrice());
printfn "------------------------------------------------------------"
This would produce:
________________ Store Items _______________________________ ============================================================ Item #: 428741 Manufacturer: Guess Category: Girls Sub-Category: Dresses Item Name: Girls 2-6X Denim Print Ruffled Dress Item Size: 3T Unit Price: 34.95 Discount Rate: 35% Discount Amount: 12.23 Marked Price: 22.72 ------------------------------------------------------------ Item #: 561150 Manufacturer: Kenneth Cole Category: Women Sub-Category: Dresses Item Name: Three-Quarter Sleeved Dress Item Size: XS Unit Price: 145.50 Discount Rate: 0% Discount Amount: 0.00 Marked Price: 145.50 ------------------------------------------------------------ Item #: 689771 Manufacturer: Calvin Klein Category: Men Sub-Category: Pants Item Name: Straight Leg Jean in Black Wash Item Size: 38/30 Unit Price: 45.00 Discount Rate: 25% Discount Amount: 11.25 Marked Price: 33.75 ------------------------------------------------------------ Press any key to close this window . . .
Copying an Array
If you have a good array you want to use in a particular scenario without messing with the original array, you can make a copy. This can be done through the copy() function of the Array module. Its signature is:
Array.copy : 'T [] -> 'T []
This function takes one argument as the array that holds the values.
Appending an Array
Appending an array consists of adding one array to another array and getting the resulting group as a new array. This operation is available through the append() function of the Array module. Its signature is:
Array.append : 'T [] -> 'T [] -> 'T []
This function takes two arguments, each is an array. The values of the second array will be added to the right side of the values of the first array. The result is a new array. Here is an example of calling the method:
let week1 = [| 8.00; 8.50; 8.00; 9.00; 8.00; 0.00; 0.00; |] let week2 = [| 8.50; 9.50; 10.00; 8.50; 9.50; 0.00; 0.00; |] let payrollTimes = Array.append week1 week2 printfn "Times Worked: %A" payrollTimes
This would produce:
Times Worked: [|8.0; 8.5; 8.0; 9.0; 8.0; 0.0; 0.0; 8.5; 9.5; 10.0; 8.5; 9.5; 0.0; 0.0|] Press any key to close this window . . .
Creating a Sub-Array
A sub-array is an array extracted from values of an existing array. To let you create a sub-array, the Array module provides the sub() function. Its signature is:
Array.sub : 'T [] -> int -> int -> 'T []
This function takes three arguments. The first is the array that holds the values. The second and the third arguments specify the range to consider in the array. The method returns a new array. Here is an example:
type OccupancyStatus =
| Other = 0
| Available = 1
| Occupied = 2
| NeedsRepair = 3
| NotReady = 4
type Apartment = {
UnitNumber : string
Bedrooms : int
Bathrooms : float
SecurityDeposit : int
MonthlyRate : int
Status : OccupancyStatus }
let apartments = [|
{ UnitNumber = "101"; Bedrooms = 2; Bathrooms = 2.00; SecurityDeposit = 650; MonthlyRate = 1150; Status = OccupancyStatus.Available }
{ UnitNumber = "102"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate = 950; Status = OccupancyStatus.NeedsRepair }
{ UnitNumber = "103"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate = 925; Status = OccupancyStatus.Available }
{ UnitNumber = "104"; Bedrooms = 3; Bathrooms = 2.00; SecurityDeposit = 850; MonthlyRate = 1350; Status = OccupancyStatus.Occupied }
{ UnitNumber = "105"; Bedrooms = 2; Bathrooms = 1.00; SecurityDeposit = 550; MonthlyRate = 1150; Status = OccupancyStatus.Available }
{ UnitNumber = "106"; Bedrooms = 3; Bathrooms = 2.00; SecurityDeposit = 1350; MonthlyRate = 850; Status = OccupancyStatus.Available }
{ UnitNumber = "107"; Bedrooms = 3; Bathrooms = 2.00; SecurityDeposit = 1285; MonthlyRate = 850; Status = OccupancyStatus.NotReady }
{ UnitNumber = "108"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 885; MonthlyRate = 500; Status = OccupancyStatus.Available }
{ UnitNumber = "109"; Bedrooms = 2; Bathrooms = 2.00; SecurityDeposit = 1150; MonthlyRate = 650; Status = OccupancyStatus.Available }
{ UnitNumber = "110"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 895; MonthlyRate = 500; Status = OccupancyStatus.Available }
|]
let units = Array.sub apartments 2 5;
printfn "====================================================="
printfn "\t\t\tMonthly"
printfn "Unit # Beds\tBaths\tRent\tDeposit Status"
printfn "-----------------------------------------------------"
for n = 0 to (Array.length units) - 1 do
printfn "%s\t%i\t%.2f\t%d\t%d\t%A" units.[n].UnitNumber units.[n].Bedrooms units.[n].Bathrooms units.[n].MonthlyRate units.[n].SecurityDeposit units.[n].Status
printfn "-----------------------------------------------------"
This would produce:
===================================================== Monthly Unit # Beds Baths Rent Deposit Status ----------------------------------------------------- 103 1 1.00 925 500 Available 104 3 2.00 1350 850 Occupied 105 2 1.00 1150 550 Available 106 3 2.00 850 1350 Available 107 3 2.00 850 1285 NotReady ----------------------------------------------------- Press any key to close this window . . .
Iterating Through an Array
Getting an Item Based on its Index
We already know that you can use a for loop to visit each member of an array. As an alternative, to let you access an item based on its index, the Array module provides a function named get. Its signature is:
Array.get : 'T [] -> int -> 'T
This function takes two arguments. The first is the array that holds the values. The second argument is the index of the item you want. Here is an example:
type Employee = {
EmployeeNumber : string
FirstName : string
LastName : string
HourlySalary : double }
let employees = [| { EmployeeNumber = "8022-3840"; FirstName = "Mark"; LastName = "Plant"; HourlySalary = 24.55 };
{ EmployeeNumber = "5840-2497"; FirstName = "Carol"; LastName = "Mylans"; HourlySalary = 16.25 };
{ EmployeeNumber = "7042-8150"; FirstName = "Frank"; LastName = "Cranston"; HourlySalary = 35.44 };
{ EmployeeNumber = "2081-7008"; FirstName = "Maria"; LastName = "Pappas"; HourlySalary = 15.26 };
{ EmployeeNumber = "4295-8475"; FirstName = "Alexander"; LastName = "Fays"; HourlySalary = 22.75 }; |]
printfn "Employees Records ___________"
for n = 0 to employees.Length - 1 do
let empl = Array.get employees n;
printfn "=-=-=-=-=-=-=-=-=-=-=-=-="
printfn "Employee Record"
printfn "-------------------------"
printfn "Employee #: %s" empl.EmployeeNumber
printfn "First Name: %s" empl.FirstName
printfn "Last Name: %s" empl.LastName
printfn "Hourly Salary: %.02F" empl.HourlySalary
printfn "=============================================="
This would produce:
Employees Records ___________ =-=-=-=-=-=-=-=-=-=-=-=-= Employee Record ------------------------- Employee #: 8022-3840 First Name: Mark Last Name: Plant Hourly Salary: 24.55 =-=-=-=-=-=-=-=-=-=-=-=-= Employee Record ------------------------- Employee #: 5840-2497 First Name: Carol Last Name: Mylans Hourly Salary: 16.25 =-=-=-=-=-=-=-=-=-=-=-=-= Employee Record ------------------------- Employee #: 7042-8150 First Name: Frank Last Name: Cranston Hourly Salary: 35.44 =-=-=-=-=-=-=-=-=-=-=-=-= Employee Record ------------------------- Employee #: 2081-7008 First Name: Maria Last Name: Pappas Hourly Salary: 15.26 =-=-=-=-=-=-=-=-=-=-=-=-= Employee Record ------------------------- Employee #: 4295-8475 First Name: Alexander Last Name: Fays Hourly Salary: 22.75 ============================================== Press any key to close this window . . .
Iterating an Array
To support the ability to execute a function on each member of an array, the Array module provides a function named iter. Its signature is:
Array.iter : ('T -> unit) -> 'T [] -> unit
This method takes two arguments. The first argument is a function that will be applied to each member of the array. The second argument is the array that holds the values. Here is an example:
type OccupancyStatus =
| Other = 0
| Available = 1
| Occupied = 2
| NeedsRepair = 3
type Apartment = {
UnitNumber : string
Bedrooms : int
Bathrooms : float
SecurityDeposit : int
MonthlyRate : int
Status : OccupancyStatus }
let apartments = Array.create 5 { UnitNumber = "101"; Bedrooms = 2; Bathrooms = 2.00; SecurityDeposit = 650; MonthlyRate = 1150; Status = OccupancyStatus.Available };
apartments.[1] <- { UnitNumber = "102"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate = 950; Status = OccupancyStatus.NeedsRepair }
apartments.[2] <- { UnitNumber = "103"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate = 925; Status = OccupancyStatus.Available }
apartments.[3] <- { UnitNumber = "104"; Bedrooms = 3; Bathrooms = 2.00; SecurityDeposit = 850; MonthlyRate = 1350; Status = OccupancyStatus.Occupied }
apartments.[4] <- { UnitNumber = "105"; Bedrooms = 2; Bathrooms = 1.00; SecurityDeposit = 550; MonthlyRate = 1150; Status = OccupancyStatus.Available }
printfn "====================================================="
printfn "\t\t\tMonthly"
printfn "Unit # Beds\tBaths\tRent\tDeposit Status"
printfn "-----------------------------------------------------"
Array.iter (fun (apart : Apartment) -> printfn "%s\t%i\t%.2f\t%d\t%d\t%A" apart.UnitNumber apart.Bedrooms apart.Bathrooms apart.MonthlyRate apart.SecurityDeposit apart.Status) apartments;
printfn "-----------------------------------------------------"
This would produce:
===================================================== Monthly Unit # Beds Baths Rent Deposit Status ----------------------------------------------------- 101 2 2.00 1150 650 Available 102 1 1.00 950 500 NeedsRepair 103 1 1.00 925 500 Available 104 3 2.00 1350 850 Occupied 105 2 1.00 1150 550 Available ----------------------------------------------------- Press any key to close this window . . .
Conditional Arrays
The Existense of an Item in an Array
To let you find out whether an item exists in an array, the Array module provides a function named exists. Its signature is:
Array.exists : ('T -> bool) -> 'T list -> bool
This is a Boolean function that takes two arguments. The first is a statement that will scan the whole array to test the condition by which a member of the array exists. If a member responds to the conditional existence, the function returns true. If no member of the array responds to that condition, the function concludes that there is no member that responds and the function returns false. Here is an example:
type Employee = {
EmployeeNumber : string
FirstName : string
LastName : string
HourlySalary : double }
let employees = [| { EmployeeNumber = "8022-3840"; FirstName = "Mark"; LastName = "Plant"; HourlySalary = 24.55 };
{ EmployeeNumber = "5840-2497"; FirstName = "Carol"; LastName = "Mylans"; HourlySalary = 16.25 };
{ EmployeeNumber = "2081-7008"; FirstName = "Maria"; LastName = "Pappas"; HourlySalary = 22.75 }; |]
type PayrollPreparation(number, times) =
let mutable nbr = number;
let mutable tms = times;
member this.EmployeeeNumber with get() = nbr and set(value) = nbr <- value;
member this.TimesWorked with get() = tms and set(value) = tms <- value;
member this.PaySummary(hourlySalary) : float array =
let mutable totalWeekTime = 0.00
for t in tms do totalWeekTime <- totalWeekTime + t
// If the employee worked under 40 hours, there is no overtime
if totalWeekTime < 40. then
[| totalWeekTime; 0.00; hourlySalary * totalWeekTime; 0.00; hourlySalary * totalWeekTime |]
else // if totalWeekTime >= 40. then
[| 40.00; totalWeekTime - 40.00; hourlySalary * 40.00; (totalWeekTime - 40.00) * (hourlySalary * 1.50); hourlySalary * 40.00 + ((totalWeekTime - 40.00) * (hourlySalary * 1.50)) |]
let pp = PayrollPreparation("5840-2497", [| 6.0; 7.5; 8.0; 6.5; 7.5; 0.0; 0.0 |]);
//let pp = PayrollPreparation("8022-3840", [| 8.50; 9.50; 10.00; 8.50; 9.50; 0.0; 0.0 |]);
if (Array.exists (fun (empl : Employee) -> empl.EmployeeNumber = pp.EmployeeeNumber) employees) then
let mutable salary = 0.00
do
for empl in employees do
if empl.EmployeeNumber = pp.EmployeeeNumber then salary <- empl.HourlySalary;
printfn "======================================"
printfn "Employee Payroll"
printfn "--------------------------------------"
printfn "Employee #:\t\t\t%s" pp.EmployeeeNumber;
printf "Full Name:\t\t\t"
do
for empl in employees do
if empl.EmployeeNumber = pp.EmployeeeNumber then printfn "%s, %s" empl.LastName empl.FirstName;
printfn "Hourly Salary:\t\t%.02F" salary;
printfn "Pay Summary___________________________"
for i = 0 to (pp.PaySummary(salary)).Length - 1 do
printfn "%s\t%0.02f" [| "Regular Time: ";
"Overtime: ";
"Regular Amount: ";
"Overtime Salary:";
"Net Pay: " |].[i]
(pp.PaySummary(salary)).[i]
printfn "--------------------------------------"
else
printfn "There is no employee with that number.";
Mapping an Array
Mapping allows you to check something on an array. If the array is made of objects, one way you can map is to get the values of only one member of the class or structure. One way you can perform this operation is to call the map() method of the Array module. Its signature is:
Array.map : ('T -> 'U) -> 'T [] -> 'U []
This function takes two arguments. The first is a function. If the array is made of objects, the function can consist of simply selecting a property or calling a method from the class. The second argument is the array that holds the values. Here is an example of calling it:
type RoadType =
| Court
| Street
| Road
| Avenue
| Boulevard
| StateHighway
| Interstate
| Unknown
type RoadSystem = {
RoadName : string
Category : RoadType
Distance : float
Location : string
Intersections : string array }
let roads = [| { RoadName = "MD 410"; Category = RoadType.Road; Distance = 13.92; Location = "From East Bethesda to Pennsy Drive in Landover Hills"; Intersections = [| "MD 355"; "MD 187"; "Maple Ave"; "MD 185"; "Colesville Rd" |] };
{ RoadName = "I 5"; Category = RoadType.Interstate; Distance = 796.432; Location = "From Mexico–United States border to South of Oregon"; Intersections = [| "SR 15"; "I 8"; "I-10"; "I-210"; "SR 99"; "I-580"; "I-80"; |] };
{ RoadName = "NE 14"; Category = RoadType.StateHighway; Distance = 203.54; Location = "From Superior, KS to SD 37"; Intersections = [| "NE 8"; "US 136"; "NE 74"; ""; "NE 41"; "US 6"; "I 80"; "US 34"; "NE 66"; "US 30"; "NE 92"; "NE 22" |] };
{ RoadName = "I 296"; Category = RoadType.Interstate; Distance = 3.43; Location = "Michigan"; Intersections = [||] };
{ RoadName = "US 2"; Category = RoadType.Road; Distance = 2571.00; Location = "Western Segment From Washington Rte 529 to I 75 in Michigan; Eastern Segment From US 11 in NY to I-95 in Maine."; Intersections = [| "US 395"; "I 15"; "US 87"; "US 83"; "I 29" |] }; |]
// Selecing on the RoadName property of the class
let roadsNames = Array.map (function (road : RoadSystem) -> road.RoadName) roads;
printf "Road Names: "
for road in roadsNames do
printf "(%s) " road
printfn "\n=------------------------------------------------="
This would produce:
Road Names: (MD 410) (I 5) (NE 14) (I 296) (US 2) =------------------------------------------------= Press any key to close this window . . .
Another way to map an array of objects is to find out whether the values of members respond to a certain condition. In the following example, we apply a condition when calling the Array.map() method to find out whether a road is an Interstate:
type RoadType =
| Court
| Street
| Road
| Avenue
| Boulevard
| StateHighway
| Interstate
| Unknown
type RoadSystem = {
RoadName : string
Category : RoadType
Distance : float
Location : string
Intersections : string array }
let roads = [| { RoadName = "MD 410"; Category = RoadType.Road; Distance = 13.92; Location = "From East Bethesda to Pennsy Drive in Landover Hills"; Intersections = [| "MD 355"; "MD 187"; "Maple Ave"; "MD 185"; "Colesville Rd" |] };
{ RoadName = "I 5"; Category = RoadType.Interstate; Distance = 796.432; Location = "From Mexico–United States border to South of Oregon"; Intersections = [| "SR 15"; "I 8"; "I-10"; "I-210"; "SR 99"; "I-580"; "I-80"; |] };
{ RoadName = "NE 14"; Category = RoadType.StateHighway; Distance = 203.54; Location = "From Superior, KS to SD 37"; Intersections = [| "NE 8"; "US 136"; "NE 74"; ""; "NE 41"; "US 6"; "I 80"; "US 34"; "NE 66"; "US 30"; "NE 92"; "NE 22" |] };
{ RoadName = "I 296"; Category = RoadType.Interstate; Distance = 3.43; Location = "Michigan"; Intersections = [||] };
{ RoadName = "US 2"; Category = RoadType.Road; Distance = 2571.00; Location = "Western Segment From Washington Rte 529 to I 75 in Michigan; Eastern Segment From US 11 in NY to I-95 in Maine."; Intersections = [| "US 395"; "I 15"; "US 87"; "US 83"; "I 29" |] }; |]
let roadsNames = Array.map (function (road : RoadSystem) -> road.Category = RoadType.Interstate) roads;
printfn "Interstates: %A" roadsNames;
This would produce:
Road Names: [|false; true; false; true; false|] Press any key to close this window . . .
Finding Items in an Array
To let you find an item in an array, the Array module has a function named find. Its signature is:
List.find : ('T -> bool) -> 'T list -> 'T
This method takes two arguments. The first is a Boolean function that applies a condition to the values of the array that is the second argument. Here is an example:
type Employee = {
EmployeeNumber : string
FirstName : string
LastName : string
HourlySalary : double }
let employees = [| { EmployeeNumber = "8022-3840"; FirstName = "Marianne"; LastName = "Jeyffers"; HourlySalary = 24.55 };
{ EmployeeNumber = "5840-2497"; FirstName = "Caroline"; LastName = "Gonzalez"; HourlySalary = 16.25 };
{ EmployeeNumber = "7042-8150"; FirstName = "Thomas"; LastName = "Cranston"; HourlySalary = 35.44 };
{ EmployeeNumber = "2081-7008"; FirstName = "Jeannette"; LastName = "Pappasie"; HourlySalary = 15.26 };
{ EmployeeNumber = "4295-8475"; FirstName = "Alexander"; LastName = "Donaldson"; HourlySalary = 22.75 }; |]
type PayrollPreparation(number, times) =
let mutable nbr = number;
let mutable tms = times;
member this.EmployeeeNumber with get() = nbr and set(value) = nbr <- value;
member this.TimesWorked with get() = tms and set(value) = tms <- value;
member this.CalculateTotalTime() =
let mutable sum = 0.00
for t in tms do sum <- sum + t
sum
member this.CalculateWeeklySalary() =
let mutable salary = 0.00;
let empl = Array.find (fun (empl : Employee) -> empl.EmployeeNumber = nbr) employees
this.CalculateTotalTime() * empl.HourlySalary
printfn "Employees Records _______________________________"
printfn "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="
printfn "\t\t\t\t\tHourly"
printfn "Empl # First Name Last Name\tSalary"
printfn "-------------------------------------------------"
for n = 0 to employees.Length - 1 do
let empl = Array.get employees n;
printfn "%s %s\t%s\t%.02F" empl.EmployeeNumber empl.FirstName empl.LastName empl.HourlySalary
printfn "================================================="
This would produce:
Employees Records _______________________________ =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Hourly Empl # First Name Last Name Salary ------------------------------------------------- 8022-3840 Marianne Jeyffers 24.55 5840-2497 Caroline Gonzalez 16.25 7042-8150 Thomas Cranston 35.44 2081-7008 Jeannette Pappasie 15.26 4295-8475 Alexander Donaldson 22.75 ================================================= Press any key to close this window . . .
Picking an Element from an Array
The Array module provides a function that can be used to apply a condition to the elements from the first item to the last. The function returns the first item that responds true to the condition. The function is named pick and its signature is:
Array.pick : ('T -> 'U option) -> 'T [] -> 'U
The condition is created as a function in the first argument of the function. That condition is created as a matching option. The second argument is the array that holds the values. Here is an example of calling the function:
type Employee = { EmployeeNumber : string FirstName : string LastName : string HourlySalary : double } let employees = [| { EmployeeNumber = "8022-3840"; FirstName = "Mark"; LastName = "Plant"; HourlySalary = 24.55 }; { EmployeeNumber = "5840-2497"; FirstName = "Carol"; LastName = "Mylans"; HourlySalary = 16.25 }; { EmployeeNumber = "2081-7008"; FirstName = "Maria"; LastName = "Pappas"; HourlySalary = 22.75 }; |] type PayrollPreparation(number, times) = let mutable nbr = number; let mutable tms = times; member this.EmployeeeNumber with get() = nbr and set(value) = nbr <- value; member this.TimesWorked with get() = tms and set(value) = tms <- value; member this.PaySummary() : float array = let mutable regularTime = 0.00 let mutable overtime = 0.00 let mutable regularAmount = 0.00 let mutable overtimeSalary = 0.00 let mutable totalWeekTime = 0.00 let mutable overtimeAmount = 0.00 let empl = Array.pick (fun (staff : Employee) -> match staff.EmployeeNumber with | nbr -> Some staff | _ -> None) employees for t in tms do totalWeekTime <- totalWeekTime + t overtimeSalary <- empl.HourlySalary * 1.50 // If the employee worked under 40 hours, there is no overtime if totalWeekTime < 40. then regularTime <- totalWeekTime regularAmount <- empl.HourlySalary * regularTime //overtime <- 0.00 //overtimeAmount <- 0.00 [| regularTime; 0.00; regularAmount; 0.00; regularAmount |] // If the employee worked over 40 hours, calculate the overtime else //if totalWeekTime >= 40. then regularTime <- 40. regularAmount <- empl.HourlySalary * 40. overtime <- totalWeekTime - 40. overtimeAmount <- overtime * overtimeSalary [| 40.; overtime; regularAmount; overtimeAmount; regularAmount + overtimeAmount |] //let pp = PayrollPreparation("5840-2497", [| 6.0; 7.5; 8.0; 6.5; 7.5; 0.0; 0.0 |]); let pp = PayrollPreparation("8022-3840", [| 8.50; 9.50; 10.00; 8.50; 9.50; 0.0; 0.0 |]); let empl = Array.pick (fun (staff : Employee) -> match staff.EmployeeNumber with | "8022-3840" -> Some staff | _ -> None) employees printfn "======================================" printfn "Employee Payroll" printfn "--------------------------------------" printfn "Employee #:\t\t%s" pp.EmployeeeNumber; printf "Full Name:\t\t" do for empl in employees do if empl.EmployeeNumber = pp.EmployeeeNumber then printfn "%s, %s" empl.LastName empl.FirstName; printfn "Hourly Salary:\t\t%.02F" empl.HourlySalary; printfn "Pay Summary___________________________" for i = 0 to 4 do printfn "%s\t%0.02f" [| "Regular Time: "; "Overtime: "; "Regular Amount: "; "Overtime Salary:"; "Net Pay: " |].[i] (pp.PaySummary()).[i] printfn "--------------------------------------"
This would produce:
====================================== Employee Payroll -------------------------------------- Employee #: 8022-3840 Full Name: Plant, Mark Hourly Salary: 24.55 Pay Summary___________________________ Regular Time: 40.00 -------------------------------------- Overtime: 6.00 -------------------------------------- Regular Amount: 982.00 -------------------------------------- Overtime Salary: 220.95 -------------------------------------- Net Pay: 1202.95 -------------------------------------- Press any key to close this window . . .
Filtering Items
Filtering items consists of applying a condition to the values of the array. The values that respond to the condition are selected and stored in a new array that is the result of the operation. To support this operation, the Array module provides the filter() function. Its signature is:
Array.filter : ('T -> bool) -> 'T [] -> 'T []
This method takes two arguments and returns an array. The first argument is a condition to apply to each value of the array that is the second argument. Here is an example:
Here is an example:
type StoreItem(number, make, category, subcategory, name, size, price, discrate) =
let mutable nbr = number
let mutable mk = make
let mutable cat = category
let mutable sub = subcategory
let mutable nm = name
let mutable sz = size
let mutable prc = price
let mutable rate = discrate
member this.ItemNumber with get() = nbr and set(value) = nbr <- value;
member this.Manufacturer with get() = mk and set(value) = mk <- value;
member this.Category with get() = cat and set(value) = cat <- value;
member this.SubCategory with get() = sub and set(value) = sub <- value;
member this.ItemName with get() = nm and set(value) = nm <- value;
member this.ItemSize with get() = sz and set(value) = sz <- value;
member this.UnitPrice with get() = prc and set(value) = prc <- value;
member this.DiscountRate with get() = rate and set(value) = rate <- value;
member this.GetDiscountAmount() = this.UnitPrice * this.DiscountRate / 100.00;
member this.MarkedPrice() = this.UnitPrice - this.GetDiscountAmount();
new(number, make, category, subcategory, name, size, price) = StoreItem(number, make, category, subcategory, name, size, price, 0.00)
let storeItems = [| StoreItem("441180", "Ralph Lauren", "Girls", "Shirts", "Girls 2-6X Short-Sleeved Mesh Polo Shirt", "3/3T", 34.95);
StoreItem("292915", "Kenneth Cole", "Women", "Dresses", "Three-Quarter Sleeved Dress", "L", 145.50, 20.00);
StoreItem("479160", "Polo Ralph Lauren", "Men", "Pants", "Classic Straight-Leg Jeans", "33W - 32L", 84.85);
StoreItem("561150", "Kenneth Cole", "Women", "Dresses", "Three-Quarter Sleeved Dress", "XS", 145.50, 20.00);
StoreItem("689771", "Calvin Klein", "Men", "Pants", "Straight Leg Jean in Black Wash", "38/30", 45.00);
StoreItem("570810", "Nautica", "Boys", "Sweaters", "Boys 2-7 Cashmere Cable V-neck Sweater", "2T/3T", 145.00);
|];
let womenClothes = Array.filter (fun (si : StoreItem) -> si.Category = "Women") storeItems;
printfn "________________ Store Items _______________________________"
printfn "============================================================"
for storeItem in womenClothes do
printfn "Item #: %s" storeItem.ItemNumber;
printfn "Manufacturer: %s" storeItem.Manufacturer;
printfn "Category: %s" storeItem.Category;
printfn "Sub-Category: %s" storeItem.SubCategory;
printfn "Item Name: %s" storeItem.ItemName;
printfn "Item Size: %s" storeItem.ItemSize;
printfn "Unit Price: %0.02f" storeItem.UnitPrice;
printfn "Discount Rate: %0.0f%s" storeItem.DiscountRate "%";
printfn "Discount Amount: %0.02f" (storeItem.GetDiscountAmount());
printfn "Marked Price: %0.02f" (storeItem.MarkedPrice());
printfn "------------------------------------------------------------"
This would produce:
________________ Store Items _______________________________ ============================================================ Item #: 292915 Manufacturer: Kenneth Cole Category: Women Sub-Category: Dresses Item Name: Three-Quarter Sleeved Dress Item Size: L Unit Price: 145.50 Discount Rate: 20% Discount Amount: 29.10 Marked Price: 116.40 ------------------------------------------------------------ Item #: 561150 Manufacturer: Kenneth Cole Category: Women Sub-Category: Dresses Item Name: Three-Quarter Sleeved Dress Item Size: XS Unit Price: 145.50 Discount Rate: 20% Discount Amount: 29.10 Marked Price: 116.40 ------------------------------------------------------------ Press any key to close this window . . .
Applying a Condition to All Items
To let you apply the same condition to all elements of an array, the Array module provides the forall() function. Its signature is:
Array.forall : ('T -> bool) -> 'T [] -> bool
The first of the two arguments is a Boolean function that applies a condition to each member of the array of the second argument. If all members of the array respond to the condition, the function returns true. If at least one member of the array doesn't apply to the condition, the function returns false. Here is an example:
type StoreItem(number, make, category, subcategory, name, size, price, discrate) = let mutable nbr = number let mutable mk = make let mutable cat = category let mutable sub = subcategory let mutable nm = name let mutable sz = size let mutable prc = price let mutable rate = discrate member this.ItemNumber with get() = nbr and set(value) = nbr <- value; member this.Manufacturer with get() = mk and set(value) = mk <- value; member this.Category with get() = cat and set(value) = cat <- value; member this.SubCategory with get() = sub and set(value) = sub <- value; member this.ItemName with get() = nm and set(value) = nm <- value; member this.ItemSize with get() = sz and set(value) = sz <- value; member this.UnitPrice with get() = prc and set(value) = prc <- value; member this.DiscountRate with get() = rate and set(value) = rate <- value; member this.GetDiscountAmount() = this.UnitPrice * this.DiscountRate / 100.00; member this.MarkedPrice() = this.UnitPrice - this.GetDiscountAmount(); new(number, make, category, subcategory, name, size, price) = StoreItem(number, make, category, subcategory, name, size, price, 0.00) let storeItems = [| StoreItem("441180", "Ralph Lauren", "Girls", "Shirts", "Girls 2-6X Short-Sleeved Mesh Polo Shirt", "3/3T", 34.95); StoreItem("292915", "Kenneth Cole", "Women", "Dresses", "Three-Quarter Sleeved Dress", "L", 145.50, 20.00); StoreItem("479160", "Polo Ralph Lauren", "Men", "Pants", "Classic Straight-Leg Jeans", "33W - 32L", 84.85); StoreItem("561150", "Kenneth Cole", "Women", "Dresses", "Three-Quarter Sleeved Dress", "XS", 145.50, 20.00); StoreItem("689771", "Calvin Klein", "Men", "Pants", "Straight Leg Jean in Black Wash", "38/30", 45.00); StoreItem("570810", "Nautica", "Boys", "Sweaters", "Boys 2-7 Cashmere Cable V-neck Sweater", "2T/3T", 145.00); |]; let areAllItemsDiscounted = Array.forall (fun (si : StoreItem) -> si.DiscountRate > 0.00) storeItems; printfn "Are all items discounted: %b" areAllItemsDiscounted
This would produce:
Are all items discounted: false Press any key to close this window . . .
Choosing a Sub-Array
If you have an array with values that can be distinguished in categories, you can create a sub-array of items that respond to a particular criterion. To support this operation, the Array module provides a function named choose. Its signature is:
Array.choose : ('T -> 'U option) -> 'T [] -> 'U []
This function takes two arguments. The first argument is a matching statement that specifies a condition by which some values will be selected. The second argument is an array that holds the values. Here is an example of calling the function:
type OccupancyStatus =
| Other = 0
| Available = 1
| Occupied = 2
| NeedsRepair = 3
| NotReady = 4
type Apartment = {
UnitNumber : string
Bedrooms : int
Bathrooms : float
SecurityDeposit : int
MonthlyRate : int
Status : OccupancyStatus }
let apartments = [|
{ UnitNumber = "101"; Bedrooms = 2; Bathrooms = 2.00; SecurityDeposit = 650; MonthlyRate = 1150; Status = OccupancyStatus.Available }
{ UnitNumber = "102"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate = 950; Status = OccupancyStatus.NeedsRepair }
{ UnitNumber = "103"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate = 925; Status = OccupancyStatus.Available }
{ UnitNumber = "104"; Bedrooms = 3; Bathrooms = 2.00; SecurityDeposit = 850; MonthlyRate = 1350; Status = OccupancyStatus.Occupied }
{ UnitNumber = "105"; Bedrooms = 2; Bathrooms = 1.00; SecurityDeposit = 550; MonthlyRate = 1150; Status = OccupancyStatus.Available }
{ UnitNumber = "106"; Bedrooms = 3; Bathrooms = 2.00; SecurityDeposit = 1350; MonthlyRate = 850; Status = OccupancyStatus.Available }
{ UnitNumber = "107"; Bedrooms = 3; Bathrooms = 2.00; SecurityDeposit = 1285; MonthlyRate = 850; Status = OccupancyStatus.NotReady }
{ UnitNumber = "108"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 885; MonthlyRate = 500; Status = OccupancyStatus.Available }
{ UnitNumber = "109"; Bedrooms = 2; Bathrooms = 2.00; SecurityDeposit = 1150; MonthlyRate = 650; Status = OccupancyStatus.Available }
{ UnitNumber = "110"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 895; MonthlyRate = 500; Status = OccupancyStatus.Available }
|]
printfn "All Apartments ======================================="
printfn " Monthly"
printfn "Unit # Beds\tBaths\tRent\tDeposit Status"
printfn "-----------------------------------------------------"
for n = 0 to (Array.length apartments) - 1 do
printfn "%s\t%i\t%.2f\t%d\t%d\t%A" apartments.[n].UnitNumber apartments.[n].Bedrooms apartments.[n].Bathrooms apartments.[n].MonthlyRate apartments.[n].SecurityDeposit apartments.[n].Status
printfn "-----------------------------------------------------"
let choose = Array.choose (fun (apart : Apartment) ->
match apart.Bedrooms with
| 1 -> Some(apart)
| _ -> None) apartments;
printfn "One-Bedroom Apartments =============================="
printfn " Monthly"
printfn "Unit # Beds\tBaths\tRent\tDeposit Status"
printfn "-----------------------------------------------------"
for n = 0 to (Array.length choose) - 1 do
printfn "%s\t%i\t%.2f\t%d\t%d\t%A" choose.[n].UnitNumber choose.[n].Bedrooms choose.[n].Bathrooms choose.[n].MonthlyRate choose.[n].SecurityDeposit choose.[n].Status
printfn "-----------------------------------------------------"
This would produce
All Apartments ======================================= Monthly Unit # Beds Baths Rent Deposit Status ----------------------------------------------------- 101 2 2.00 1150 650 Available 102 1 1.00 950 500 NeedsRepair 103 1 1.00 925 500 Available 104 3 2.00 1350 850 Occupied 105 2 1.00 1150 550 Available 106 3 2.00 850 1350 Available 107 3 2.00 850 1285 NotReady 108 1 1.00 500 885 Available 109 2 2.00 650 1150 Available 110 1 1.00 500 895 Available ----------------------------------------------------- One-Bedroom Apartments ============================== Monthly Unit # Beds Baths Rent Deposit Status ----------------------------------------------------- 102 1 1.00 950 500 NeedsRepair 103 1 1.00 925 500 Available 108 1 1.00 500 885 Available 110 1 1.00 500 895 Available ----------------------------------------------------- Press any key to close this window . . .
Further Operations on Arrays
Getting a Reversed Array
Reversing an array consists of changing the order of its value. The reverse can be done using the rev() function of the Array module. Its signature is:
Array.rev : 'T [] -> 'T []
Here is an example:
type OccupancyStatus =
| Other = 0
| Available = 1
| Occupied = 2
| NeedsRepair = 3
| NotReady = 4
type Apartment = {
UnitNumber : string
Bedrooms : int
Bathrooms : float
SecurityDeposit : int
MonthlyRate : int
Status : OccupancyStatus }
let apartments = [|
{ UnitNumber = "101"; Bedrooms = 2; Bathrooms = 2.00; SecurityDeposit = 650; MonthlyRate = 1150; Status = OccupancyStatus.Available }
{ UnitNumber = "102"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate = 950; Status = OccupancyStatus.NeedsRepair }
{ UnitNumber = "103"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate = 925; Status = OccupancyStatus.Available }
{ UnitNumber = "104"; Bedrooms = 3; Bathrooms = 2.00; SecurityDeposit = 850; MonthlyRate = 1350; Status = OccupancyStatus.Occupied }
{ UnitNumber = "105"; Bedrooms = 2; Bathrooms = 1.00; SecurityDeposit = 550; MonthlyRate = 1150; Status = OccupancyStatus.Available }
{ UnitNumber = "106"; Bedrooms = 3; Bathrooms = 2.00; SecurityDeposit = 1350; MonthlyRate = 850; Status = OccupancyStatus.Available }
{ UnitNumber = "107"; Bedrooms = 3; Bathrooms = 2.00; SecurityDeposit = 1285; MonthlyRate = 850; Status = OccupancyStatus.NotReady }
{ UnitNumber = "108"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 885; MonthlyRate = 500; Status = OccupancyStatus.Available }
{ UnitNumber = "109"; Bedrooms = 2; Bathrooms = 2.00; SecurityDeposit = 1150; MonthlyRate = 650; Status = OccupancyStatus.Available }
{ UnitNumber = "110"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 895; MonthlyRate = 500; Status = OccupancyStatus.Available }
|]
let reversedOrder = Array.rev apartments;
printfn "All Apartments ======================================="
printfn " Monthly"
printfn "Unit # Beds\tBaths\tRent\tDeposit Status"
printfn "-----------------------------------------------------"
for apart in reversedOrder do
printfn "%s\t%i\t%.2f\t%d\t%d\t%A" apart.UnitNumber apart.Bedrooms apart.Bathrooms apart.MonthlyRate apart.SecurityDeposit apart.Status
printfn "-----------------------------------------------------"
This would produce:
All Apartments ======================================= Monthly Unit # Beds Baths Rent Deposit Status ----------------------------------------------------- 110 1 1.00 500 895 Available 109 2 2.00 650 1150 Available 108 1 1.00 500 885 Available 107 3 2.00 850 1285 NotReady 106 3 2.00 850 1350 Available 105 2 1.00 1150 550 Available 104 3 2.00 1350 850 Occupied 103 1 1.00 925 500 Available 102 1 1.00 950 500 NeedsRepair 101 2 2.00 1150 650 Available ----------------------------------------------------- Press any key to close this window . . .
Number-Based Functions of Arrays
Introduction
The Array module of the Microsoft.FSharp.Collections namespace provides various functions to perform numeric calculations on the items of an array. To perform these calculations, all the members of the array must be numbers, whether integers or floats.
The Sum of Members of an Array
The sum() function is used to calculate the total of all the items of an array. The signature of that function is:
Array.sum : ^T [] -> ^T
This function takes one argument as the array that holds the values. Here is an example of calling the Array.sum() function:
type Employee = {
EmployeeNumber : string
FirstName : string
LastName : string
HourlySalary : double }
let employees = [| { EmployeeNumber = "8022-3840"; FirstName = "Mark"; LastName = "Plant"; HourlySalary = 24.55 };
{ EmployeeNumber = "5840-2497"; FirstName = "Carol"; LastName = "Mylans"; HourlySalary = 16.25 };
{ EmployeeNumber = "2081-7008"; FirstName = "Maria"; LastName = "Pappas"; HourlySalary = 22.75 };
{ EmployeeNumber = "2080-4813"; FirstName = "James"; LastName = "Alexanders"; HourlySalary = 22.25 }; |]
type PayrollPreparation(number, times) =
let mutable nbr = number;
let mutable tms = times;
member this.EmployeeeNumber with get() = nbr and set(value) = nbr <- value;
member this.TimesWorked with get() = tms and set(value) = tms <- value;
member this.PaySummary() : float array =
let mutable regularTime = 0.00
let mutable overtime = 0.00
let mutable regularAmount = 0.00
let mutable overtimeSalary = 0.00
let mutable overtimeAmount = 0.00
let totalTime = Array.sum times
let empl = Array.find (fun (empl : Employee) -> empl.EmployeeNumber = nbr) employees
overtimeSalary <- empl.HourlySalary * 1.50
// If the employee worked under 40 hours, there is no overtime
if totalTime < 40. then
regularTime <- totalTime
regularAmount <- empl.HourlySalary * regularTime
//overtime <- 0.00
//overtimeAmount <- 0.00
[| regularTime; 0.00; regularAmount; 0.00; regularAmount |]
// If the employee worked over 40 hours, calculate the overtime
else //if totalWeekTime >= 40. then
regularTime <- 40.
regularAmount <- empl.HourlySalary * 40.
overtime <- totalTime - 40.
overtimeAmount <- overtime * overtimeSalary
[| 40.; overtime; regularAmount; overtimeAmount; regularAmount + overtimeAmount |]
// let pp = PayrollPreparation("5840-2497", [| 6.0; 7.5; 8.0; 6.5; 7.5; 0.0; 0.0 |]);
// let pp = PayrollPreparation("8022-3840", [| 8.50; 9.50; 10.00; 8.50; 9.50; 0.0; 0.0 |]);
let pp = PayrollPreparation("2080-4813", [| 8.50; 9.50; 10.50; 10.00; 9.00; 0.0; 0.0 |]);
let empl = Array.find (fun (empl : Employee) -> empl.EmployeeNumber = "2080-4813") employees
printfn "======================================"
printfn "Employee Payroll"
printfn "--------------------------------------"
printfn "Employee #:\t\t%s" pp.EmployeeeNumber;
printf "Full Name:\t\t"
do
for empl in employees do
if empl.EmployeeNumber = pp.EmployeeeNumber then printfn "%s, %s" empl.LastName empl.FirstName;
printfn "Hourly Salary:\t\t%.02F" empl.HourlySalary;
printfn "Pay Summary___________________________"
for i = 0 to 4 do
printfn "%s\t%0.02f" [| "Regular Time: ";
"Overtime: ";
"Regular Amount: ";
"Overtime Salary:";
"Net Pay: " |].[i]
(pp.PaySummary()).[i]
printfn "--------------------------------------"
This would produce:
====================================== Employee Payroll -------------------------------------- Employee #: 2080-4813 Full Name: Alexanders, James Hourly Salary: 22.25 Pay Summary___________________________ Regular Time: 40.00 -------------------------------------- Overtime: 7.50 -------------------------------------- Regular Amount: 982.00 -------------------------------------- Overtime Salary: 276.19 -------------------------------------- Net Pay: 1258.19 -------------------------------------- Press any key to close this window . . .
To let you apply a condition by which the sum should be calculated, the Array module provides a function named sumBy. Its signature is:
Array.sumBy : ('T -> ^U) -> 'T [] -> ^U
This function takes two arguments. The first is the function to apply to the array that is the second argument.
|
|||
Previous | Copyright © 2014-2024, FunctionX | Thursday 02 November 2024 | Next |
|