我们在介绍新的F#数组之前,还介绍一下基础的知识,我这里把MSDN中的相关的代码拿出来,做专门的注解。
您可以创建数组在几个方面。您可以创建一个分号隔开以“|”为开始和结束,如以下示例所示。
f#
let array1 = [| 1; 2; 3 ; 4 |]
你也可以把每个元素放在一个单独的行,在这种情况下,分号分隔符是省略的。
f#
let array1 =
[|
1
2
3
4
|]
所有数组元素的类型必须一致。下面的代码会导致一个错误,因为1.0是一个浮点数,2和3是整数。
f#
// Causes an error.//let array2 = [| 1.0; 2; 3 |]
您还可以使用序列表达式创建数组。下面是一个示例,该示例创建一个广场1到10的整数数组。
f#
let array3 = [| for i in 1 .. 10 -> i * i |]
创建一个数组的所有元素的初始化为零,使用Array.zeroCreate。
f#
let arrayOfTenZeroes : intarray =Array.zeroCreate 10
您通过使用点操作符(.)和方括号([和]),可以访问数组元素。
f#
array1.[0]
数组索引从0开始。
您还可以访问数组元素通过使用片表示法,它使您能够指定一个数组的子串。片符号的例子。
f#
// Accesses elementsfrom 0 to 2.
array1.[0..2]
// Accesses elementsfrom the beginning of the array to 2.
array1.[..2]
// Accesses elementsfrom 2 to the end of the array.
array1.[2..]
当使用片符号时,创建一个新数组。
Array.get一个元素。Array.length给一个数组的长度。Array.set一个元素设置为指定的值。下面的代码示例说明了这些函数的使用。
f#
let array1 = Array.create 10 ""聽
for i in 0 .. array1.Length - 1 do
Array.set array1 i (i.ToString())
for i in 0 .. array1.Length - 1 do
printf "%s " (Array.get array1 i)
如下所示的输出。
0 1 2 3 4 5 6 7 8 9
几个函数创建数组不需要现有的数组。Array.empty创建一个新数组,不包含任何元素。Array.create创建一个指定大小的数组和集合的所有元素提供值。Array.init创建一个数组,给定一个维度和一个函数生成元素。Array.zeroCreate创建一个数组的所有元素的数组初始化为零值的类型。下面的代码演示了这些函数。
f#
let myEmptyArray = Array.empty
printfn "Length of empty array: %d" myEmptyArray.Length
printfn "Array of floats set to 5.0: %A" (Array.create 10 5.0)
printfn "Array of squares: %A" (Array.init 10 (fun index-> index * index))
let (myZeroArray : floatarray) =Array.zeroCreate 10
如下所示的输出。
Length of emptyarray: 0
Area of floats set to5.0: [|5.0; 5.0; 5.0; 5.0; 5.0; 5.0; 5.0; 5.0; 5.0; 5.0|]
Array of squares:[|0; 1; 4; 9; 16; 25; 36; 49; 64; 81|]
Array.copy创建一个新数组,其中包含的元素复制从现有的数组。注意,副本是浅拷贝,这意味着如果元素类型是引用类型,只有引用复制,而不是底层对象。下面的代码示例说明了这一点。
f#
open System.Text
let firstArray : StringBuilder array = Array.init 3 (fun index -> newStringBuilder(""))
let secondArray = Array.copy firstArray
// Reset an elementof the first array to a new value.
firstArray.[0] <- new StringBuilder("Test1")
// Change an elementof the first array.
firstArray.[1].Insert(0,"Test2") |> ignore
printfn "%A" firstArray
printfn "%A" secondArray
前面的代码的输出如下:
[|Test1; Test2; |]
[|; Test2; |]
字符串 TEST1只出现在第一个数组,因为赋值操作创建一个新的元素覆盖 firstArray但不影响原来的引用空字符串 secondArray。而字符串test2出现在两个数组,因为 插入操作不影响两个数组的引用。
Array.sub生成一个新的数组从子范围的一个数组。您指定的子范围提供起始索引和长度。下面的代码演示了使用Array.sub。
f#
let a1 = [| 0 .. 99 |]
let a2 = Array.sub a1 5 10
printfn "%A" a2
子阵列的输出显示五元素开始,包含10个元素。
[|5; 6; 7; 8; 9; 10;11; 12; 13; 14|]
Array.append创建一个新的数组通过结合现有的两个数组。
下面的代码演示了Array.append。
f#
printfn "%A" (Array.append [| 1; 2; 3|] [| 4; 5; 6|])
前面的代码如下所示的输出。
[|1; 2; 3; 4; 5; 6|]
Array.choose选择一个数组的元素包含在一个新的数组。下面在这个例子中,元素类型 int和选择是一个多项式函数的结果, elem * elem - 1一个浮点数。
f#
printfn "%A" (Array.choose (fun elem -> if elem% 2 = 0 then
Some(float (elem*elem - 1))
else
None) [| 1 .. 10 |])
前面的代码如下所示的输出。
[|3.0; 15.0; 35.0;63.0; 99.0|]
Array.collect运行一个指定的函数在每个现有的数组的数组元素,然后收集元素生成的函数,结合成一个新的数组。下面的代码演示了Array.collect。
f#
printfn "%A" (Array.collect (fun elem-> [| 0 .. elem |]) [| 1; 5; 10|])
前面的代码如下所示的输出。
[|0; 1; 0; 1; 2; 3;4; 5; 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10|]
Array.concat需要一个序列的阵列,结合成一个数组。下面的代码演示了Array.concat。
f#
let multiplicationTable max = seq { for i in 1 .. max -> [| for j in 1 .. max -> (i, j, i*j) |] }
printfn "%A" (Array.concat (multiplicationTable 3))
前面的代码如下所示的输出。
[|(1, 1, 1); (1, 2,2); (1, 3, 3); (2, 1, 2); (2, 2, 4); (2, 3, 6); (3, 1, 3);
(3, 2, 6); (3, 3, 9)|]
Array.filter接受一个布尔条件函数并生成一个新数组。
f#
printfn "%A" (Array.filter (fun elem -> elem % 2 = 0) [| 1 .. 10|])
前面的代码如下所示的输出。
[|2; 4; 6; 8; 10|]
Array.rev生成一个新的逆序数组。下面的代码演示了Array.rev。
f#
let stringReverse (s: string) =
System.String(Array.rev (s.ToCharArray()))
printfn "%A" (stringReverse("!dlrow olleH"))
前面的代码如下所示的输出。
"Helloworld!"
使用管道操作符(| >),如以下示例所示。
f#
[| 1 .. 10 |]
|> Array.filter (fun elem -> elem % 2 = 0)
|> Array.choose (fun elem -> if (elem <> 8) thenSome(elem*elem) else None)
|> Array.rev
|> printfn "%A"
输出
[|100; 36; 16; 4|]
这个过程是先把【1,2,3,4,5,6,7,8,9,10】这个数组filter,选出偶数,然后把不等于8的元素乘方,最后倒序。