Partilhar via


Segmentações

Este artigo explica como tirar fatias de tipos F# existentes e como definir suas próprias fatias.

Em F#, uma fatia é um subconjunto de qualquer tipo de dados. As fatias são semelhantes aos indexadores, mas em vez de produzir um único valor da estrutura de dados subjacente, elas produzem várias. As fatias usam a sintaxe do .. operador para selecionar o intervalo de índices especificados em um tipo de dados. Para obter mais informações, consulte o artigo de referência de expressão de looping.

Atualmente, o F# tem suporte intrínseco para fatiamento de cadeias de caracteres, listas, matrizes e matrizes multidimensionais (2D, 3D, 4D). O fatiamento é mais comumente usado com matrizes e listas F#. Você pode adicionar fatiamento aos tipos de dados personalizados usando o GetSlice método em sua definição de tipo ou em uma extensão de tipo no escopo.

Fatiamento de listas e matrizes F#

Os tipos de dados mais comuns que são fatiados são listas e matrizes F#. O exemplo a seguir demonstra como fatiar listas:

// Generate a list of 100 integers
let fullList = [ 1 .. 100 ]

// Create a slice from indices 1-5 (inclusive)
let smallSlice = fullList[1..5]
printfn $"Small slice: {smallSlice}"

// Create a slice from the beginning to index 5 (inclusive)
let unboundedBeginning = fullList[..5]
printfn $"Unbounded beginning slice: {unboundedBeginning}"

// Create a slice from an index to the end of the list
let unboundedEnd = fullList[94..]
printfn $"Unbounded end slice: {unboundedEnd}"

Dividir matrizes é como fatiar listas:

// Generate an array of 100 integers
let fullArray = [| 1 .. 100 |]

// Create a slice from indices 1-5 (inclusive)
let smallSlice = fullArray[1..5]
printfn $"Small slice: {smallSlice}"

// Create a slice from the beginning to index 5 (inclusive)
let unboundedBeginning = fullArray[..5]
printfn $"Unbounded beginning slice: {unboundedBeginning}"

// Create a slice from an index to the end of the list
let unboundedEnd = fullArray[94..]
printfn $"Unbounded end slice: {unboundedEnd}"

Antes do F# 6, o fatiamento usava a sintaxe expr.[start..finish] com o extra .. Se desejar, você ainda pode usar essa sintaxe. Para obter mais informações, consulte RFC FS-1110.

Fatiamento de matrizes multidimensionais

O F# suporta matrizes multidimensionais na biblioteca principal do F#. Tal como acontece com matrizes unidimensionais, fatias de matrizes multidimensionais também podem ser úteis. No entanto, a introdução de dimensões adicionais exige uma sintaxe ligeiramente diferente para que você possa tirar fatias de linhas e colunas específicas.

Os exemplos a seguir demonstram como fatiar uma matriz 2D:

// Generate a 3x3 2D matrix
let A = array2D [[1;2;3];[4;5;6];[7;8;9]]
printfn $"Full matrix:\n {A}"

// Take the first row
let row0 = A[0,*]
printfn $"{row0}"

// Take the first column
let col0 = A[*,0]
printfn $"{col0}"

// Take all rows but only two columns
let subA = A[*,0..1]
printfn $"{subA}"

// Take two rows and all columns
let subA' = A[0..1,*]
printfn $"{subA}"

// Slice a 2x2 matrix out of the full 3x3 matrix
let twoByTwo = A[0..1,0..1]
printfn $"{twoByTwo}"

Definindo fatias para outras estruturas de dados

A biblioteca principal do F# define fatias para um conjunto limitado de tipos. Se desejar definir fatias para mais tipos de dados, você pode fazê-lo na própria definição de tipo ou em uma extensão de tipo.

Por exemplo, veja como você pode definir fatias para a ArraySegment<T> classe para permitir a manipulação conveniente de dados:

open System

type ArraySegment<'TItem> with
    member segment.GetSlice(start, finish) =
        let start = defaultArg start 0
        let finish = defaultArg finish segment.Count
        ArraySegment(segment.Array, segment.Offset + start, finish - start)

let arr = ArraySegment [| 1 .. 10 |]
let slice = arr[2..5] //[ 3; 4; 5]

Outro exemplo usando os Span<T> tipos e ReadOnlySpan<T> :

open System

type ReadOnlySpan<'T> with
    member sp.GetSlice(startIdx, endIdx) =
        let s = defaultArg startIdx 0
        let e = defaultArg endIdx sp.Length
        sp.Slice(s, e - s)

type Span<'T> with
    member sp.GetSlice(startIdx, endIdx) =
        let s = defaultArg startIdx 0
        let e = defaultArg endIdx sp.Length
        sp.Slice(s, e - s)

let printSpan (sp: Span<int>) =
    let arr = sp.ToArray()
    printfn $"{arr}"

let sp = [| 1; 2; 3; 4; 5 |].AsSpan()
printSpan sp[0..] // [|1; 2; 3; 4; 5|]
printSpan sp[..5] // [|1; 2; 3; 4; 5|]
printSpan sp[0..3] // [|1; 2; 3|]
printSpan sp[1..3] // |2; 3|]

As fatias F# incorporadas incluem o fim

Todas as fatias intrínsecas em F# são end-inclusive; ou seja, o limite superior está incluído na fatia. Para uma determinada fatia com índice x inicial e índice yfinal, a fatia resultante incluirá o valor yth.

// Define a new list
let xs = [1 .. 10]

printfn $"{xs[2..5]}" // Includes the 5th index

Fatias vazias F# incorporadas

Listas, matrizes, sequências, cadeias de caracteres, matrizes multidimensionais (2D, 3D, 4D) em F# produzirão uma fatia vazia se a sintaxe puder produzir uma fatia que não existe.

Considere o seguinte exemplo:

let l = [ 1..10 ]
let a = [| 1..10 |]
let s = "hello!"

let emptyList = l[-2..(-1)]
let emptyArray = a[-2..(-1)]
let emptyString = s[-2..(-1)]

Importante

Os desenvolvedores de C# podem esperar que eles lancem uma exceção em vez de produzir uma fatia vazia. Esta é uma decisão de design enraizada no fato de que coleções vazias compõem em F#. Uma lista F# vazia pode ser composta com outra lista F#, uma string vazia pode ser adicionada a uma string existente e assim por diante. Pode ser comum pegar fatias com base em valores passados como parâmetros, e ser tolerante a out-of-bounds > produzindo uma coleção vazia se encaixa com a natureza composicional do código F#.

Fatias de índice fixo para matrizes 3D e 4D

Para matrizes 3D e 4D de F#, você pode "corrigir" um determinado índice e fatiar outras dimensões com esse índice fixo.

Para ilustrar isso, considere a seguinte matriz 3D:

z = 0

x\y 0 1
0 0 1
1 2 3

z = 1

x\y 0 1
0 4 5
1 6 7

Se quiser extrair a fatia [| 4; 5 |] da matriz, use uma fatia de índice fixo.

let dim = 2
let m = Array3D.zeroCreate<int> dim dim dim

let mutable count = 0

for z in 0..dim-1 do
    for y in 0..dim-1 do
        for x in 0..dim-1 do
            m[x,y,z] <- count
            count <- count + 1

// Now let's get the [4;5] slice!
m[*, 0, 1]

A última linha fixa os y índices e z da matriz 3D e toma o x resto dos valores que correspondem à matriz.

Consulte também