Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W tym artykule wyjaśniono, jak wykonywać wycinki z istniejących typów języka F# i jak definiować własne wycinki.
W języku F# wycinek jest podzbiorem dowolnego typu danych. Wycinki są podobne do indeksatorów, ale zamiast zwracać pojedynczą wartość z podstawowej struktury danych, dają one wiele. Wycinki używają ..
składni operatora, aby wybrać zakres określonych indeksów w typie danych. Aby uzyskać więcej informacji, zobacz artykuł referencyjny dotyczący wyrażeń pętli.
Język F# ma obecnie wewnętrzną obsługę fragmentowania ciągów, list, tablic i tablic wielowymiarowych (2D, 3D, 4D). Fragmentowanie jest najczęściej używane z tablicami i listami języka F#. Fragmentowanie można dodać do niestandardowych typów danych przy użyciu GetSlice
metody w definicji typu lub w rozszerzeniu typu w zakresie.
Fragmentowanie list i tablic języka F#
Najczęściej używane typy danych to listy i tablice języka F#. W poniższym przykładzie pokazano, jak podzielić listy na wycinki:
// 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}"
Tablice fragmentowania są podobne do list fragmentowania:
// 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}"
Przed F# 6 fragmentowanie używało składni expr.[start..finish]
z dodatkowym .
elementem . Jeśli wybierzesz tę składnię, nadal możesz użyć tej składni. Aby uzyskać więcej informacji, zobacz RFC FS-1110.
Fragmentowanie tablic wielowymiarowych
Język F# obsługuje tablice wielowymiarowe w podstawowej bibliotece języka F#. Podobnie jak w przypadku tablic jednowymiarowych, wycinki tablic wielowymiarowych mogą być również przydatne. Jednak wprowadzenie dodatkowych wymiarów nakazuje nieco inną składnię, dzięki czemu można wykonywać wycinki określonych wierszy i kolumn.
W poniższych przykładach pokazano, jak podzielić tablicę 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}"
Definiowanie wycinków dla innych struktur danych
Podstawowa biblioteka języka F# definiuje wycinki dla ograniczonego zestawu typów. Jeśli chcesz zdefiniować wycinki dla większej liczby typów danych, możesz to zrobić w samej definicji typu lub w rozszerzeniu typu.
Na przykład poniżej przedstawiono sposób definiowania wycinków dla ArraySegment<T> klasy w celu umożliwienia wygodnego manipulowania danymi:
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]
Inny przykład użycia typów Span<T> i 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|]
Wbudowane wycinki języka F# są kompleksowe
Wszystkie wycinki wewnętrzne w języku F# są kompleksowe; oznacza to, że górna granica jest zawarta w wycinku. W przypadku danego wycinka z indeksem x
początkowym i końcowym indeksem y
wynikowy wycinek będzie zawierać wartość yth .
// Define a new list
let xs = [1 .. 10]
printfn $"{xs[2..5]}" // Includes the 5th index
Wbudowane puste wycinki języka F#
Listy języka F#, tablice, sekwencje, ciągi, tablice wielowymiarowe (2D, 3D, 4D) spowodują wygenerowanie pustego wycinka, jeśli składnia może utworzyć wycinkę, która nie istnieje.
Rozważmy następujący przykład:
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)]
Ważne
Deweloperzy języka C# mogą oczekiwać, że zgłaszają wyjątek, a nie tworzą pustego wycinka. Jest to decyzja projektowa zakorzeniona w tym, że puste kolekcje tworzą się w języku F#. Pusta lista języka F# może składać się z innej listy języka F#. Pusty ciąg można dodać do istniejącego ciągu itd. Często można wykonywać wycinki na podstawie wartości przekazywanych jako parametrów i tolerancyjnej poza granicami > , tworząc pustą kolekcję zgodną z charakterem składowym kodu języka F#.
Wycinki indeksu stałego dla tablic 3D i 4D
W przypadku tablic 3D i 4D języka F# można "naprawić" określony indeks i podzielić inne wymiary na stały indeks.
Aby to zilustrować, rozważmy następującą tablicę 3D:
z = 0
x\y | 0 | 1 |
---|---|---|
0 | 0 | 1 |
1 | 2 | 3 |
z = 1
x\y | 0 | 1 |
---|---|---|
0 | 100 | 5 |
1 | 6 | 7 |
Jeśli chcesz wyodrębnić wycinkę z tablicy, użyj wycinka [| 4; 5 |]
indeksu stałego.
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]
Ostatni wiersz naprawia y
indeksy i z
tablicy 3D i pobiera pozostałe x
wartości odpowiadające macierzy.