Share via


Matrizes (F#)

As matrizes são coleções de tamanho fixo, com base em zero, mutáveis de elementos de dados consecutivos que são todos do mesmo tipo.

Criação de matrizes

Você pode criar arrays de várias maneiras. Você pode criar um conjunto de pequeno listando valores consecutivos entre [| e |] e separados por ponto e vírgula, como mostrado nos exemplos a seguir.

let array1 = [| 1; 2; 3 |]

Você também pode colocar cada elemento em uma linha separada, caso em que o separador de ponto e vírgula é opcional.

let array1 = 
    [|
        1
        2
        3
     |]

O tipo de elementos de matriz é inferido dos literais usados e deve ser consistente. O código a seguir gera um erro porque 1.0 é uma float e 2 e 3 são inteiros.

// Causes an error.
// let array2 = [| 1.0; 2; 3 |] 

Você também pode usar expressões de seqüência para criar matrizes. Veja a seguir um exemplo que cria uma matriz dos quadrados dos números inteiros de 1 a 10.

let array3 = [| for i in 1 .. 10 -> i * i |]

Para criar uma matriz em que todos os elementos são inicializados como zero, o uso Array.zeroCreate.

let arrayOfTenZeroes : int array = Array.zeroCreate 10

Acessando Elementos

Você pode acessar os elementos de matriz, usando um operador de ponto (.) e colchetes ([e]).

array1.[0]

Índices da matriz começam com 0.

Você também pode acessar os elementos da matriz usando a notação de fatia, o que permite que você especifique um subintervalo do array. Seguem exemplos de notação de fatia.

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

Quando é usada a notação de fatia, uma nova cópia da matriz é criada.

Módulos e tipos de matriz

O tipo de todas as matrizes de F# é o.Tipo do NET Framework Array. Portanto, a F# arrays oferecem suporte a toda a funcionalidade disponível em Array.

O módulo biblioteca Microsoft.FSharp.Collections.Array oferece suporte a operações em matrizes unidimensionais. Os módulos Array2D, Array3D, e Array4D contêm funções que oferecem suporte a operações em matrizes de dois, três e quatro dimensões, respectivamente. Você pode criar matrizes de fileira superior a quatro por meio de Array.

Funções simples

Array.Get obtém de um elemento. Length retorna o comprimento de uma matriz. Set define um elemento com um valor especificado. O exemplo de código a seguir ilustra o uso dessas funções.

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)

A saída é da seguinte maneira.

0 1 2 3 4 5 6 7 8 9

Funções que criar matrizes

Várias funções criar matrizes sem a necessidade de um array existente. Array.Empty cria uma nova matriz que não contém quaisquer elementos. Array.Create cria uma matriz de um tamanho especificado e define todos os elementos para os valores fornecidos. Array.Init cria uma matriz de uma dimensão e uma função para gerar os elementos. Array.zeroCreate cria uma matriz em que todos os elementos são inicializados para o valor zero para o tipo da matriz. O código a seguir demonstra a essas funções.

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 : float array) = Array.zeroCreate 10

A saída é da seguinte maneira.

Length of empty array: 0
Area of floats set to 5.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|]

Obter cria uma nova matriz que contém elementos que são copiados de um array existente. Observe que a cópia é uma cópia superficial, o que significa que, se o tipo de elemento é um tipo de referência, apenas a referência é copiada, não o objeto subjacente. O exemplo de código a seguir ilustra isso.

open System.Text

let firstArray : StringBuilder array = Array.init 3 (fun index -> new StringBuilder(""))
let secondArray = Array.copy firstArray
// Reset an element of the first array to a new value.
firstArray.[0] <- new StringBuilder("Test1")
// Change an element of the first array.
firstArray.[1].Insert(0, "Test2") |> ignore
printfn "%A" firstArray
printfn "%A" secondArray

A saída do código anterior é o seguinte:

[|Test1; Test2; |]
[|; Test2; |]

A seqüência de caracteres Test1 só aparece na primeira matriz porque a operação de criação de um novo elemento substitui a referência na firstArray mas não afeta a referência original para uma seqüência vazia que ainda está presente no secondArray. A seqüência de caracteres Test2 aparece nas duas matrizes, porque o Insert operação na StringBuilder afeta o tipo base StringBuilder o objeto, ela é referenciado em ambos os arrays.

Array.sub gera uma nova matriz a partir de um subintervalo de uma matriz. Você pode especificar o subintervalo fornecendo o índice inicial e o comprimento. O código a seguir demonstra o uso de Array.sub.

let a1 = [| 0 .. 99 |]
let a2 = Array.sub a1 5 10
printfn "%A" a2

A saída mostra que o subarray começa no elemento 5 e contém elementos de 10.

[|5; 6; 7; 8; 9; 10; 11; 12; 13; 14|]

Array.Append cria uma nova matriz, combinando duas matrizes existentes.

O código a seguir demonstra Array.append.

printfn "%A" (Array.append [| 1; 2; 3|] [| 4; 5; 6|])

A saída do código anterior é o seguinte.

[|1; 2; 3; 4; 5; 6|]

Array.Choose seleciona os elementos de uma matriz para incluir um novo array. O código a seguir demonstra Array.choose. Observe que o tipo de elemento da matriz não precisa corresponder ao tipo do valor retornado no tipo de opção. Neste exemplo, o tipo de elemento é int e a opção é o resultado de uma função polinomial, elem*elem - 1, como um flutuante ponto número.

printfn "%A" (Array.choose (fun elem -> if elem % 2 = 0 then
                                            Some(float (elem*elem - 1))
                                        else
                                            None) [| 1 .. 10 |])

A saída do código anterior é o seguinte.

[|3.0; 15.0; 35.0; 63.0; 99.0|]

Array.Collect executa uma função especificada em cada elemento da matriz de um array existente e os elementos gerados pela função de coleta e as combina em uma nova matriz. O código a seguir demonstra Array.collect.

printfn "%A" (Array.collect (fun elem -> [| 0 .. elem |]) [| 1; 5; 10|])

A saída do código anterior é o seguinte.

[|0; 1; 0; 1; 2; 3; 4; 5; 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10|]

Array.Concat leva a uma seqüência de arrays e as combina em um único array. O código a seguir demonstra Array.concat.

let multiplicationTable max = seq { for i in 1 .. max -> [| for j in 1 .. max -> (i, j, i*j) |] }
printfn "%A" (Array.concat (multiplicationTable 3))

A saída do código anterior é o seguinte.

[|(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 usa uma função de condição booleana e gera uma nova matriz que contém apenas os elementos da matriz de entrada para o qual a condição for verdadeira. O código a seguir demonstra Array.filter.

printfn "%A" (Array.filter (fun elem -> elem % 2 = 0) [| 1 .. 10|])

A saída do código anterior é o seguinte.

[|2; 4; 6; 8; 10|]

Array.rev gera uma nova matriz invertendo a ordem de um array existente. O código a seguir demonstra Array.rev.

let stringReverse (s: string) =
    System.String(Array.rev (s.ToCharArray()))

printfn "%A" (stringReverse("!dlrow olleH"))

A saída do código anterior é o seguinte.

"Hello world!"

Você pode facilmente combinar funções do módulo de matriz que transformam os arrays usando o operador de pipeline (| >), conforme mostrado no exemplo a seguir.

[| 1 .. 10 |]
|> Array.filter (fun elem -> elem % 2 = 0)
|> Array.choose (fun elem -> if (elem <> 8) then Some(elem*elem) else None)
|> Array.rev
|> printfn "%A"

A saída é

[|100; 36; 16; 4|]

Matrizes multidimensionais

Uma matriz multidimensional pode ser criada, mas não há nenhuma sintaxe para escrever um literal de matriz multidimensional. Use o operador array2D para criar uma matriz de uma seqüência de seqüências de elementos de matriz. As seqüências podem ser literais de matriz ou lista. Por exemplo, o código a seguir cria uma matriz bidimensional.

let my2DArray = array2D [ [ 1; 0]; [0; 1] ]

Você também pode usar a função Array2D.init para inicializar conjuntos de duas dimensões e é semelhante a funções estão disponíveis para conjuntos de dimensões de três e quatro. Essas funções têm uma função que é usada para criar os elementos. Para criar uma matriz bidimensional que contém elementos definidos como um valor inicial em vez de especificar uma função, use o Array2D.create função, que também está disponível para conjuntos de dimensões de até quatro. O exemplo de código a seguir primeiro mostra como criar uma matriz de matrizes que contêm os elementos desejados e, em seguida, usa Array2D.init para gerar a matriz bidimensional desejado.

let arrayOfArrays = [| [| 1.0; 0.0 |]; [|0.0; 1.0 |] |]
let twoDimensionalArray = Array2D.init 2 2 (fun i j -> arrayOfArrays.[i].[j]) 

Matriz de indexação e a sintaxe de fatiamento há suporte para matrizes até a classificação 4. Quando você especificar um índice em várias dimensões, você use vírgulas para separar os índices, conforme ilustrado no exemplo de código a seguir.

twoDimensionalArray.[0, 1] <- 1.0

O tipo de uma matriz bidimensional é escrito como <type>[,] (por exemplo, int[,], double[,]), e o tipo de uma matriz tridimensional é escrito como <type>[,,], e assim por diante para conjuntos de dimensões maiores.

Apenas um subconjunto das funções disponíveis para matrizes unidimensionais também está disponível para matrizes multidimensionais. Para obter mais informações, consulte Módulo de Collections.Array (F #), Módulo de Collections.Array2D (F#), Módulo de Collections.Array3D (F#) e Módulo de Collections.Array4D (F#).

Funções booleanas em Arrays

As funções array. Exists e Array.exists2 testar os elementos em matrizes de um ou dois, respectivamente. Essas funções levar a uma função de teste e retornar true se não houver um elemento (ou o par de elemento para Array.exists2) que satisfaça a condição.

O código a seguir demonstra o uso de Array.exists e Array.exists2. Nestes exemplos, são criadas novas funções aplicando-se apenas um dos argumentos, nesses casos, o argumento de função.

let allNegative = Array.exists (fun elem -> abs (elem) = elem) >> not
printfn "%A" (allNegative [| -1; -2; -3 |])
printfn "%A" (allNegative [| -10; -1; 5 |])
printfn "%A" (allNegative [| 0 |])
let haveEqualElement = Array.exists2 (fun elem1 elem2 -> elem1 = elem2)
printfn "%A" (haveEqualElement [| 1; 2; 3 |] [| 3; 2; 1|])

A saída do código anterior é o seguinte.

true
false
false
true

Da mesma forma, a função Array.forall testa uma matriz para determinar se cada elemento satisfaz uma condição booleana. A variação Array.forall2 faz a mesma coisa usando uma função booleana que envolve os elementos de duas matrizes de tamanho igual. O código a seguir ilustra o uso dessas funções.

let allPositive = Array.forall (fun elem -> elem > 0)
printfn "%A" (allPositive [| 0; 1; 2; 3 |])
printfn "%A" (allPositive [| 1; 2; 3 |])
let allEqual = Array.forall2 (fun elem1 elem2 -> elem1 = elem2)
printfn "%A" (allEqual [| 1; 2 |] [| 1; 2 |])
printfn "%A" (allEqual [| 1; 2 |] [| 2; 1 |])

A saída para esses exemplos é o seguinte.

false
true
true
false

A pesquisa de Arrays

Array.Find usa uma função booleana e retorna o primeiro elemento para o qual a função retornará true, ou gera uma KeyNotFoundException se nenhum elemento que satisfaça a condição for encontrado. Array.findIndex é parecido com Array.find, exceto que ela retorna o índice do elemento em vez de um elemento em si.

O seguinte código usa Array.find e Array.findIndex para localizar um número que é um quadrado perfeito e cubo perfeito.

let arrayA = [| 2 .. 100 |]
let delta = 1.0e-10
let isPerfectSquare (x:int) =
    let y = sqrt (float x)
    abs(y - round y) < delta
let isPerfectCube (x:int) =
    let y = System.Math.Pow(float x, 1.0/3.0)
    abs(y - round y) < delta
let element = Array.find (fun elem -> isPerfectSquare elem && isPerfectCube elem) arrayA
let index = Array.findIndex (fun elem -> isPerfectSquare elem && isPerfectCube elem) arrayA
printfn "The first element that is both a square and a cube is %d and its index is %d." element index

A saída é da seguinte maneira.

The first element that is both a square and a cube is 64 and its index is 62.

Array.tryFind é parecido com Array.find, exceto que o seu resultado é um tipo de opção e ela retorna None se for encontrado nenhum elemento. Array.tryFinddeve ser usado em vez de Array.find Quando você não souber se um elemento correspondente está no array. Da mesma forma, Array.tryFindIndex é parecido com Array.findIndex , exceto que o tipo de opção é o valor de retorno. Se nenhum elemento for encontrado, a opção é None.

O código a seguir demonstra o uso de Array.tryFind. Esse código depende do código anterior.

let delta = 1.0e-10
let isPerfectSquare (x:int) =
    let y = sqrt (float x)
    abs(y - round y) < delta
let isPerfectCube (x:int) =
    let y = System.Math.Pow(float x, 1.0/3.0)
    abs(y - round y) < delta
let lookForCubeAndSquare array1 =
    let result = Array.tryFind (fun elem -> isPerfectSquare elem && isPerfectCube elem) array1
    match result with
    | Some x -> printfn "Found an element: %d" x
    | None -> printfn "Failed to find a matching element."

lookForCubeAndSquare [| 1 .. 10 |]
lookForCubeAndSquare [| 100 .. 1000 |]
lookForCubeAndSquare [| 2 .. 50 |]

A saída é da seguinte maneira.

Found an element: 1
Found an element: 729

Use Array.tryPick quando você precisa transformar um elemento, além de encontrá-las. O resultado é o primeiro elemento para o qual a função retorna o elemento transformado como um valor de opção ou None se não há tal elemento for encontrado.

O código a seguir mostra o uso de Array.tryPick. Nesse caso, em vez de uma expressão lambda, várias funções do auxiliar local são definidas para simplificar o código.

let findPerfectSquareAndCube array1 =
    let delta = 1.0e-10
    let isPerfectSquare (x:int) =
        let y = sqrt (float x)
        abs(y - round y) < delta
    let isPerfectCube (x:int) =
        let y = System.Math.Pow(float x, 1.0/3.0)
        abs(y - round y) < delta
    // intFunction : (float -> float) -> int -> int
    // Allows the use of a floating point function with integers.
    let intFunction function1 number = int (round (function1 (float number)))
    let cubeRoot x = System.Math.Pow(x, 1.0/3.0)
    // testElement: int -> (int * int * int) option
    // Test an element to see whether it is a perfect square and a perfect
    // cube, and, if so, return the element, square root, and cube root
    // as an option value. Otherwise, return None.
    let testElement elem = 
        if isPerfectSquare elem && isPerfectCube elem then
            Some(elem, intFunction sqrt elem, intFunction cubeRoot elem)
        else None
    match Array.tryPick testElement array1 with
    | Some (n, sqrt, cuberoot) -> printfn "Found an element %d with square root %d and cube root %d." n sqrt cuberoot
    | None -> printfn "Did not find an element that is both a perfect square and a perfect cube."

findPerfectSquareAndCube [| 1 .. 10 |]
findPerfectSquareAndCube [| 2 .. 100 |]
findPerfectSquareAndCube [| 100 .. 1000 |]
findPerfectSquareAndCube [| 1000 .. 10000 |]
findPerfectSquareAndCube [| 2 .. 50 |]

A saída é da seguinte maneira.

Found an element 1 with square root 1 and cube root 1.
Found an element 64 with square root 8 and cube root 4.
Found an element 729 with square root 27 and cube root 9.
Found an element 4096 with square root 64 and cube root 16.

Executar cálculos em Arrays

O Array.average função retorna a média de cada elemento em uma matriz. Ele é limitado para tipos de elementos que oferecem suporte a divisão exata por um inteiro, que inclui os tipos de ponto flutuante, mas os tipos de não integrais. O Array.averageBy função retorna a média dos resultados de chamar uma função em cada elemento. Uma matriz do tipo integral, você pode usar Array.averageBy e têm a função de converter a cada elemento em uma flutuante aponte o tipo da computação.

Use Array.max ou Array.min para obter o elemento máximo ou mínimo, se o tipo de elemento oferece suporte a ele. Da mesma forma, Array.maxBy e Array.minBy permitem uma função a ser executado pela primeira vez, talvez para transformar a um tipo que ofereça suporte a comparação.

Array.Sum adiciona os elementos de uma matriz, e Array.sumBy chama uma função em cada elemento e adiciona os resultados juntos.

Para executar uma função em cada elemento em uma matriz sem armazenar os valores de retorno, use Array.iter. Para uma função que envolve duas matrizes de tamanho igual, use Array.iter2. Se você também precisará manter uma matriz dos resultados da função, use estejam ou Array.map2, que opera em duas matrizes, ao mesmo tempo.

As variações Array.iteri e Array.iteri2 permitem que o índice do elemento a ser envolvidos na computação; o mesmo é verdadeiro para Array.mapi e Array.mapi2.

As funções Array.fold, Array.foldBack, Array.reduce, Array.reduceBack, Array.scan, e Array.scanBack executar algoritmos que envolvem todos os elementos de uma matriz. Da mesma forma, as variações Array.fold2 e Array.foldBack2 executar cálculos em duas matrizes.

Essas funções para realizar cálculos correspondem às funções do mesmo nome de módulo lista. Para obter exemplos de uso, consulte Listas (F#).

A modificação de Arrays

Set define um elemento com um valor especificado. Array.Fill define um intervalo de elementos em uma matriz com um valor especificado. O código a seguir fornece um exemplo de Array.fill.

let arrayFill1 = [| 1 .. 25 |]
Array.fill arrayFill1 2 20 0
printfn "%A" arrayFill1

A saída é da seguinte maneira.

[|1; 2; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 23; 24; 25|]

Você pode usar Array.blit para copiar uma subseção de um array para outro array.

Converter para e de outros tipos de

Array.ofList cria uma matriz em uma lista. Array.ofSeq cria uma matriz de uma seqüência. Array.toList e Array.toSeq converter esses outros tipos de coleção do tipo de matriz.

Classificação de matrizes

Use array. Sort para classificar uma matriz usando a função de comparação genérico. Use Array.sortBy especificar uma função que gera um valor, conhecido como um chave, para classificar usando a função de comparação genérico na chave. Use Array.sortWith se você deseja fornecer uma função personalizada de comparação. Array.sort, Array.sortBy, e Array.sortWith todos retornam a matriz classificada como uma nova matriz. As variações Array.sortInPlace, Array.sortInPlaceBy, e Array.sortInPlaceWith modificam a matriz existente em vez de retornar uma nova.

Arrays e tuplas

As funções Array.zip e Array.unzip converter matrizes de pares de tupla tuplas de arrays e vice-versa. Array.zip3 e Array.unzip3 são semelhantes, exceto que eles funcionam com tuplas de três elementos ou tuplas de três matrizes.

Computações paralelas em Arrays

O módulo Array.Parallel contém funções para realizar cálculos paralelos em arrays. Este módulo não está disponível em aplicativos destinados a versões do.NET Framework anterior à versão 4.

Consulte também

Outros recursos

Referência de linguagem do F#

Tipos de F#