切片Slices

在 F # 中,切片是 GetSlice 在其定义或范围内 类型扩展中具有方法的任何数据类型的子集。In F#, a slice is a subset of any data type that has a GetSlice method in its definition or in an in-scope type extension. 它最常用于 F # 数组和列表。It is most commonly used with F# arrays and lists. 本文介绍如何从现有的 F # 类型中获取切片,以及如何定义自己的切片。This article explains how to take slices from existing F# types and how to define your own slices.

切片与 索引器相似,但它不是从基础数据结构产生单个值,而是生成多个值。Slices are similar to indexers, but instead of yielding a single value from the underlying data structure, they yield multiple ones.

F # 目前对切片字符串、列表、数组和二维数组具有内部支持。F# currently has intrinsic support for slicing strings, lists, arrays, and 2D arrays.

带有 F # 列表和数组的基本切片Basic slicing with F# lists and arrays

切片最常见的数据类型是 F # 列表和数组。The most common data types that are sliced are F# lists and arrays. 下面的示例演示如何通过列表执行此操作:The following example demonstrates how to do this with lists:

// 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: %A" smallSlice

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

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

切片数组与切片列表类似:Slicing arrays is just like slicing lists:

// 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: %A" smallSlice

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

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

切片多维数组Slicing multidimensional arrays

F # 支持 F # 核心库中的多维数组。F# supports multidimensional arrays in the F# core library. 与一维数组一样,多维数组的切片也很有用。As with one-dimensional arrays, slices of multidimensional arrays can also be useful. 但是,附加维度的引入要求使用略微不同的语法,以便能够获取特定行和列的切片。However, the introduction of additional dimensions mandates a slightly different syntax so that you can take slices of specific rows and columns.

下面的示例演示如何切分二维数组:The following examples demonstrate how to slice a 2D array:

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

// Take the first row
let row0 = A.[0,*]
printfn "Row 0: %A" row0

// Take the first column
let col0 = A.[*,0]
printfn "Column 0: %A" col0

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

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

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

F # core 库当前没有 GetSlice 为三维数组定义。The F# core library does not currently define GetSlice for 3D arrays. 如果要对三维数组或其他维度的其他数组进行切片,请 GetSlice 自行定义成员。If you wish to slice 3D arrays or other arrays of more dimensions, define the GetSlice member yourself.

为其他数据结构定义切片Defining slices for other data structures

F # 核心库定义了有限类型集的切片。The F# core library defines slices for a limited set of types. 如果要定义更多数据类型的切片,可以在类型定义本身或类型扩展中执行此操作。If you wish to define slices for more data types, you can do so either in the type definition itself or in a type extension.

例如,下面介绍了如何为类定义切片, ArraySegment<T> 以方便进行数据操作:For example, here's how you might define slices for the ArraySegment<T> class to allow for convenient data manipulation:

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]

使用和类型的另一个示例 Span<T> ReadOnlySpan<T>Another example using the Span<T> and ReadOnlySpan<T> types:

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 "%A" 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|]

内置 F # 切片包含结尾Built-in F# slices are end-inclusive

F # 中的所有内部切片都是结尾的;也就是说,切片中包括上限。All intrinsic slices in F# are end-inclusive; that is, the upper bound is included in the slice. 对于具有起始索引 x 和结束索引的给定切片 y ,生成的切片将包含 yth 值。For a given slice with starting index x and ending index y, the resulting slice will include the yth value.

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

printfn "%A" xs.[2..5] // Includes the 5th index

另请参阅See also