Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Ez a cikk bemutatja, hogyan készíthet szeleteket meglévő F#-típusokból, és hogyan határozhatja meg saját szeleteit.
Az F#-ban a szeletek bármilyen adattípus részhalmazai. A szeletek hasonlóak az indexelőkhöz, de ahelyett, hogy egyetlen értéket adnak a mögöttes adatstruktúrából, több értéket is eredményeznek. A szeletek az .. operátor szintaxisával jelölik ki a megadott indexek tartományát egy adattípusban. További információkért tekintse meg a cikluskifejezések referenciacikkét.
Az F# jelenleg belső támogatást nyújt a sztringek, listák, tömbök és többdimenziós (2D, 3D, 4D) tömbök szeleteléséhez. A szeletelést leggyakrabban F# tömbökkel és listákkal használják. Szeletelést adhat hozzá az egyéni adattípusokhoz a GetSlice típusdefinícióban vagy a hatókörön belüli típuskiterjesztésben található metódus használatával.
F#-listák és tömbök szeletelése
A szeletelt leggyakoribb adattípusok az F# listák és tömbök. Az alábbi példa a listák szeletelésére mutat be példát:
// 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}"
A tömbök szeletelése pont olyan, mint a szeletelő listák:
// 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}"
Az F# 6 előtt a szeletelés a szintaxist expr.[start..finish] használta az extra .. Ha úgy dönt, továbbra is használhatja ezt a szintaxist. További információ: RFC FS-1110.
Többdimenziós tömbök szeletelése
Az F# támogatja a többdimenziós tömböket az F#-magtárban. Az egydimenziós tömbökhöz hasonlóan a többdimenziós tömbök szeletei is hasznosak lehetnek. A további dimenziók bevezetése azonban kissé eltérő szintaxist igényel, így adott sorok és oszlopok szeleteit is felveheti.
Az alábbi példák bemutatják, hogyan szeletelhet kétdimenziós tömböt:
// 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}"
Szeletek definiálása más adatstruktúrákhoz
Az F#-magtár korlátozott típusok szeleteit határozza meg. Ha több adattípushoz szeretne szeleteket definiálni, ezt a típusdefinícióban vagy egy típuskiterjesztésben teheti meg.
Az alábbiakban például az osztály szeleteit határozhatja meg, hogy lehetővé tegye a ArraySegment<T> kényelmes adatkezelést:
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]
Egy másik példa az és ReadOnlySpan<T> a Span<T> típusok használatával:
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|]
A beépített F#-szeletek teljes körűek
Az F# minden belső szelete végfoglaló; vagyis a felső határ szerepel a szeletben. Egy kezdő indexet x és záró indexet ytartalmazó szelet esetében az eredményként kapott szelet tartalmazza az yth értéket.
// Define a new list
let xs = [1 .. 10]
printfn $"{xs[2..5]}" // Includes the 5th index
Beépített F# üres szeletek
Az F#-listák, tömbök, sorozatok, sztringek, többdimenziós (2D, 3D, 4D) tömbök mind üres szeletet hoznak létre, ha a szintaxis nem létező szeletet hozhat létre.
Vegye figyelembe a következő példát:
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)]
Fontos
A C#-fejlesztők arra számíthatnak, hogy ezek kivételt okoznak, nem pedig üres szeletet hoznak létre. Ez a tervezési döntés abban gyökerezik, hogy az üres gyűjtemények F#-ban jelennek meg. Az üres F#-listák egy másik F#-listával is összeállíthatók, egy üres sztring hozzáadható egy meglévő sztringhez stb. Gyakori, hogy paraméterekként átadott értékek alapján készít szeleteket, és tűri a korlátokon > kívüli elemeket, ha üres gyűjteményt hoz létre, amely megfelel az F# kód összetételének.
Rögzített indexszeletek 3D és 4D tömbökhöz
F# 3D és 4D tömbök esetén "kijavíthat" egy adott indexet, és más dimenziókat is felszeletelhet az index rögzítettével.
Ennek szemléltetéséhez vegye figyelembe a következő 3D tömböt:
z = 0
| x\y | 0 | 1 |
|---|---|---|
| 0 | 0 | 1 |
| 1 | 2 | 3 |
z = 1
| x\y | 0 | 1 |
|---|---|---|
| 0 | 4 | 5 |
| 1 | 6 | 7 |
Ha ki szeretné nyerni a szeletet [| 4; 5 |] a tömbből, használjon rögzített indexszeletet.
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]
Az utolsó sor kijavítja a y 3D tömb indexeit és z a mátrixnak megfelelő többi x értéket.