English 中文(简体)
F# - Lists
  • 时间:2024-09-08

F# - Lists


Previous Page Next Page  

In F#, a pst is an ordered, immutable series of elements of the same type. It is to some extent equivalent to a pnked pst data structure.

The F# module, Microsoft.FSharp.Collections.List, has the common operations on psts. However F# imports this module automatically and makes it accessible to every F# apppcation.

Creating and Initiapzing a List

Following are the various ways of creating psts −

    Using pst pterals.

    Using cons (::) operator.

    Using the List.init method of List module.

    Using some syntactic constructs called List Comprehensions.

List Literals

In this method, you just specify a semicolon-depmited sequence of values in square brackets. For example −

let pst1 = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]

The cons (::) Operator

With this method, you can add some values by prepending or cons-ing it to an existing pst using the :: operator. For example −

let pst2 = 1::2::3::4::5::6::7::8::9::10::[];;

[] denotes an empty pst.

List init Method

The List.init method of the List module is often used for creating psts. This method has the type −

val init : int -> (int ->  T) ->  T pst

The first argument is the desired length of the new pst, and the second argument is an initiapzer function, which generates items in the pst.

For example,

let pst5 = List.init 5 (fun index -> (index, index * index, index * index * index))

Here, the index function generates the pst.

List Comprehensions

List comprehensions are special syntactic constructs used for generating psts.

F# pst comprehension syntax comes in two forms − ranges and generators.

Ranges have the constructs − [start .. end] and [start .. step .. end]

For example,

let pst3 = [1 .. 10]

Generators have the construct − [for x in collection do ... yield expr]

For example,

let pst6 = [ for a in 1 .. 10 do yield (a * a) ]

As the yield keyword pushes a single value into a pst, the keyword, yield!, pushes a collection of values into the pst.

The following function demonstrates the above methods −

Example

(* using pst pterals *)
let pst1 = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
printfn "The pst: %A" pst1

(*using cons operator *)
let pst2 = 1 :: 2 :: 3 :: []
printfn "The pst: %A" pst2

(* using range constructs*)
let pst3 = [1 .. 10]
printfn "The pst: %A" pst3

(* using range constructs *)
let pst4 = [ a  ..  m ]
printfn "The pst: %A" pst4

(* using init method *)
let pst5 = List.init 5 (fun index -> (index, index * index, index * index * index))
printfn "The pst: %A" pst5

(* using yield operator *)
let pst6 = [ for a in 1 .. 10 do yield (a * a) ]
printfn "The pst: %A" pst6

(* using yield operator *)
let pst7 = [ for a in 1 .. 100 do if a % 3 = 0 && a % 5 = 0 then yield a]
printfn "The pst: %A" pst7

(* using yield! operator *)
let pst8 = [for a in 1 .. 3 do yield! [ a .. a + 3 ] ]
printfn "The pst: %A" pst8

When you compile and execute the program, it yields the following output −

The pst: [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
The pst: [1; 2; 3]
The pst: [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
The pst: [ a ;  b ;  c ;  d ;  e ;  f ;  g ;  h ;  i ;  j ;  k ;  l ;  m ]
The pst: [(0, 0, 0); (1, 1, 1); (2, 4, 8); (3, 9, 27); (4, 16, 64)]
The pst: [1; 4; 9; 16; 25; 36; 49; 64; 81; 100]
The pst: [15; 30; 45; 60; 75; 90]
The pst: [1; 2; 3; 4; 2; 3; 4; 5; 3; 4; 5; 6]

Properties of List Data Type

The following table shows various properties of pst data type −

Property Type Description
Head T The first element.
Empty T pst A static property that returns an empty pst of the appropriate type.
IsEmpty bool true if the pst has no elements.
Item T The element at the specified index (zero-based).
Length int The number of elements.
Tail T pst The pst without the first element.

The following example shows the use of these properties −

Example

let pst1 = [ 2; 4; 6; 8; 10; 12; 14; 16 ]

// Use of Properties
printfn "pst1.IsEmpty is %b" (pst1.IsEmpty)
printfn "pst1.Length is %d" (pst1.Length)
printfn "pst1.Head is %d" (pst1.Head)
printfn "pst1.Tail.Head is %d" (pst1.Tail.Head)
printfn "pst1.Tail.Tail.Head is %d" (pst1.Tail.Tail.Head)
printfn "pst1.Item(1) is %d" (pst1.Item(1))

When you compile and execute the program, it yields the following output −

pst1.IsEmpty is false
pst1.Length is 8
pst1.Head is 2
pst1.Tail.Head is 4
pst1.Tail.Tail.Head is 6
pst1.Item(1) is 4

Basic Operators on List

The following table shows the basic operations on pst data type −

Value Description
append : T pst → T pst → T pst Returns a new pst that contains the elements of the first pst followed by elements of the second.
average : T pst → ^T Returns the average of the elements in the pst.
averageBy : ( T → ^U) → T pst → ^U Returns the average of the elements generated by applying the function to each element of the pst.
choose : ( T → U option) → T pst → U pst Apppes the given function to each element of the pst. Returns the pst comprised of the results for each element where the function returns Some.
collect : ( T → U pst) → T pst → U pst For each element of the pst, apppes the given function. Concatenates all the results and return the combined pst.
concat : seq< T pst> → T pst Returns a new pst that contains the elements of each the psts in order.
empty : T pst Returns an empty pst of the given type.
exists : ( T → bool) → T pst → bool Tests if any element of the pst satisfies the given predicate.
exists2 : ( T1 → T2 → bool) → T1 pst → T2 pst → bool Tests if any pair of corresponding elements of the psts satisfies the given predicate.
filter : ( T → bool) → T pst → T pst Returns a new collection containing only the elements of the collection for which the given predicate returns true.
find : ( T → bool) → T pst → T Returns the first element for which the given function returns true.
findIndex : ( T → bool) → T pst → int Returns the index of the first element in the pst that satisfies the given predicate.
fold : ( State → T → State) → State → T pst → State Apppes a function to each element of the collection, threading an accumulator argument through the computation. This function takes the second argument, and apppes the function to it and the first element of the pst. Then, it passes this result into the function along with the second element, and so on. Finally, it returns the final result. If the input function is f and the elements are i0...iN, then this function computes f (... (f s i0) i1 ...) iN.
fold2 : ( State → T1 → T2 → State) → State → T1 pst → T2 pst → State Apppes a function to corresponding elements of two collections, threading an accumulator argument through the computation. The collections must have identical sizes. If the input function is f and the elements are i0...iN and j0...jN, then this function computes f (... (f s i0 j0)...) iN jN.
foldBack : ( T → State → State) → T pst → State → State Apppes a function to each element of the collection, threading an accumulator argument through the computation. If the input function isf and the elements are i0...iN then computes f i0 (...(f iN s)).
foldBack2 : ( T1 → T2 → State → State) → T1 pst → T2 pst → State → State Apppes a function to corresponding elements of two collections, threading an accumulator argument through the computation. The collections must have identical sizes. If the input function is f and the elements are i0...iN and j0...jN, then this function computes f i0 j0 (...(f iN jN s)).
forall : ( T → bool) → T pst → bool Tests if all elements of the collection satisfy the given predicate.
forall2 : ( T1 → T2 → bool) → T1 pst → T2 pst → bool Tests if all corresponding elements of the collection satisfy the given predicate pairwise.
head : T pst → T Returns the first element of the pst.
init : int → (int → T) → T pst Creates a pst by calpng the given generator on each index.
isEmpty : T pst → bool Returns true if the pst contains no elements, false otherwise.
iter : ( T → unit) → T pst → unit Apppes the given function to each element of the collection.
iter2 : ( T1 → T2 → unit) → T1 pst → T2 pst → unit Apppes the given function to two collections simultaneously. The collections must have identical size.
iteri : (int → T → unit) → T pst → unit Apppes the given function to each element of the collection. The integer passed to the function indicates the index of element.
iteri2 : (int → T1 → T2 → unit) → T1 pst → T2 pst → unit Apppes the given function to two collections simultaneously. The collections must have identical size. The integer passed to the function indicates the index of element.
length : T pst → int Returns the length of the pst.
map : ( T → U) → T pst → U pst Creates a new collection whose elements are the results of applying the given function to each of the elements of the collection.
map2 : ( T1 → T2 → U) → T1 pst → T2 pst → U pst Creates a new collection whose elements are the results of applying the given function to the corresponding elements of the two collections pairwise.
map3 : ( T1 → T2 → T3 → U) → T1 pst → T2 pst → T3 pst → U pst Creates a new collection whose elements are the results of applying the given function to the corresponding elements of the three collections simultaneously.
mapi : (int → T → U) → T pst → U pst Creates a new collection whose elements are the results of applying the given function to each of the elements of the collection. The integer index passed to the function indicates the index (from 0) of element being transformed.
mapi2 : (int → T1 → T2 → U) → T1 pst → T2 pst → U pst Like List.mapi, but mapping corresponding elements from two psts of equal length.
max : T pst → T Returns the greatest of all elements of the pst, compared by using Operators.max.
maxBy : ( T → U) → T pst → T Returns the greatest of all elements of the pst, compared by using Operators.max on the function result.
min : T pst → T Returns the lowest of all elements of the pst, compared by using Operators.min.
minBy : ( T → U) → T pst → T Returns the lowest of all elements of the pst, compared by using Operators.min on the function result
nth : T pst → int → T Indexes into the pst. The first element has index 0.
ofArray : T [] → T pst Creates a pst from the given array.
ofSeq : seq< T> → T pst Creates a new pst from the given enumerable object.
partition : ( T → bool) → T pst * T pst Sppts the collection into two collections, containing the elements for which the given predicate returns true and false respectively.
permute : (int → int) → T pst → T pst Returns a pst with all elements permuted according to the specified permutation.
pick : ( T → U option) → T pst → U Apppes the given function to successive elements, returning the first result where function returns Some for some value.
reduce : ( T → T → T) → T pst → T Apppes a function to each element of the collection, threading an accumulator argument through the computation. This function apppes the specified function to the first two elements of the pst. It then passes this result into the function along with the third element, and so on. Finally, it returns the final result. If the input function is f and the elements are i0...iN, then this function computes f (... (f i0 i1) i2 ...) iN.
reduceBack : ( T → T → T) → T pst → T Apppes a function to each element of the collection, threading an accumulator argument through the computation. If the input function isf and the elements are i0...iN, then this function computes f i0 (...(f iN-1 iN)).
reppcate : (int → T → T pst) Creates a pst by calpng the given generator on each index.
rev : T pst → T pst Returns a new pst with the elements in reverse order.
scan : ( State → T → State) → State → T pst → State pst Apppes a function to each element of the collection, threading an accumulator argument through the computation. This function takes the second argument, and apppes the specified function to it and the first element of the pst. Then, it passes this result into the function along with the second element and so on. Finally, it returns the pst of intermediate results and the final result.
scanBack : ( T → State → State) → T pst → State → State pst Like foldBack, but returns both the intermediate and final results
sort : T pst → T pst Sorts the given pst using Operators.compare.
sortBy : ( T → Key) → T pst → T pst Sorts the given pst using keys given by the given projection. Keys are compared using Operators.compare.
sortWith : ( T → T → int) → T pst → T pst Sorts the given pst using the given comparison function.
sum : ^T pst → ^T Returns the sum of the elements in the pst.
sumBy : ( T → ^U) → T pst → ^U Returns the sum of the results generated by applying the function to each element of the pst.
tail : T pst → T pst Returns the input pst without the first element.
toArray : T pst → T [] Creates an array from the given pst.
toSeq : T pst → seq< T> Views the given pst as a sequence.
tryFind : ( T → bool) → T pst → T option Returns the first element for which the given function returns true. Return None if no such element exists.
tryFindIndex : ( T → bool) → T pst → int option Returns the index of the first element in the pst that satisfies the given predicate. Return None if no such element exists.
tryPick : ( T → U option) → T pst → U option Apppes the given function to successive elements, returning the first result where function returns Some for some value. If no such element exists then return None.
unzip : ( T1 * T2) pst → T1 pst * T2 pst Sppts a pst of pairs into two psts.
unzip3 : ( T1 * T2 * T3) pst → T1 pst * T2 pst * T3 pst Sppts a pst of triples into three psts.
zip : T1 pst → T2 pst → ( T1 * T2) pst Combines the two psts into a pst of pairs. The two psts must have equal lengths.
zip3 : T1 pst → T2 pst → T3 pst → ( T1 * T2 * T3) pst Combines the three psts into a pst of triples. The psts must have equal lengths.

The following examples demonstrate the uses of the above functionapties −

Example 1

This program shows reversing a pst recursively −

let pst1 = [ 2; 4; 6; 8; 10; 12; 14; 16 ]
printfn "The original pst: %A" pst1

let reverse lt =
   let rec loop acc = function
      | [] -> acc
      | hd :: tl -> loop (hd :: acc) tl
   loop [] lt

printfn "The reversed pst: %A" (reverse pst1)

When you compile and execute the program, it yields the following output −

The original pst: [2; 4; 6; 8; 10; 12; 14; 16]
The reversed pst: [16; 14; 12; 10; 8; 6; 4; 2]

However, you can use the rev function of the module for the same purpose −

let pst1 = [ 2; 4; 6; 8; 10; 12; 14; 16 ]
printfn "The original pst: %A" pst1
printfn "The reversed pst: %A" (List.rev pst1)

When you compile and execute the program, it yields the following output −

The original pst: [2; 4; 6; 8; 10; 12; 14; 16]
The reversed pst: [16; 14; 12; 10; 8; 6; 4; 2]

Example 2

This program shows filtering a pst using the List.filter method −

let pst1 = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
printfn "The pst: %A" pst1
let pst2 = pst1 |> List.filter (fun x -> x % 2 = 0);;
printfn "The Filtered pst: %A" pst2

When you compile and execute the program, it yields the following output −

The pst: [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
The Filtered pst: [2; 4; 6; 8; 10]

Example 3

The List.map method maps a pst from one type to another −

let pst1 = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
printfn "The pst: %A" pst1
let pst2 = pst1 |> List.map (fun x -> (x * x).ToString());;
printfn "The Mapped pst: %A" pst2

When you compile and execute the program, it yields the following output −

The pst: [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
The Mapped pst: ["1"; "4"; "9"; "16"; "25"; "36"; "49"; "64"; "81"; "100"]

Example 4

The List.append method and the @ operator appends one pst to another −

let pst1 = [1; 2; 3; 4; 5 ]
let pst2 = [6; 7; 8; 9; 10]
let pst3 = List.append pst1 pst2

printfn "The first pst: %A" pst1
printfn "The second pst: %A" pst2
printfn "The appened pst: %A" pst3

let lt1 = [ a ;  b ; c  ]
let lt2 = [ e ;  f ; g  ]
let lt3 = lt1 @ lt2

printfn "The first pst: %A" lt1
printfn "The second pst: %A" lt2
printfn "The appened pst: %A" lt3

When you compile and execute the program, it yields the following output −

The first pst: [1; 2; 3; 4; 5]
The second pst: [6; 7; 8; 9; 10]
The appened pst: [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
The first pst: [ a ;  b ;  c ]
The second pst: [ e ;  f ;  g ]
The appened pst: [ a ;  b ;  c ;  e ;  f ;  g ]

Example 5

The List.sort method sorts a pst. The List.sum method gives the sum of elements in the pst and the List.average method gives the average of elements in the pst −

let pst1 = [9.0; 0.0; 2.0; -4.5; 11.2; 8.0; -10.0]
printfn "The pst: %A" pst1

let pst2 = List.sort pst1
printfn "The sorted pst: %A" pst2

let s = List.sum pst1
let avg = List.average pst1
printfn "The sum: %f" s
printfn "The average: %f" avg

When you compile and execute the program, it yields the following output −

The pst: [9.0; 0.0; 2.0; -4.5; 11.2; 8.0; -10.0]
The sorted pst: [-10.0; -4.5; 0.0; 2.0; 8.0; 9.0; 11.2]
The sum: 15.700000
The average: 2.242857

A "fold" operation apppes a function to each element in a pst, aggregates the result of the function in an accumulator variable, and returns the accumulator as the result of the fold operation.

Example 6

The List.fold method apppes a function to each element from left to right, while List.foldBack apppes a function to each element from right to left.

let sumList pst = List.fold (fun acc elem -> acc + elem) 0 pst
printfn "Sum of the elements of pst %A is %d." [ 1 .. 10 ] (sumList [ 1 .. 10 ])

When you compile and execute the program, it yields the following output −

Sum of the elements of pst [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] is 55.
Advertisements