Sorozatok
A sorozat egy logikai elemsorozat, amely egyetlen típusból áll. A sorozatok különösen akkor hasznosak, ha nagy méretű, rendezett adatgyűjteményt használ, de nem feltétlenül számít az összes elem használatára. Az egyes sorozatelemeket csak szükség szerint számítjuk ki, így a sorozatok jobb teljesítményt nyújtanak, mint egy lista olyan helyzetekben, amikor nem minden elemet használnak. A szekvenciákat a seq<'T>
típus jelöli, amely a IEnumerable<T>. Ezért az interfészt megvalósító IEnumerable<T> .NET-típusok sorozatként használhatók. A Seq modul támogatja a sorozatokat érintő manipulációkat.
Sorozatkifejezések
A szekvenciakifejezés egy olyan kifejezés, amely egy sorozatot értékel ki. A szekvenciakifejezések számos űrlapot tartalmazhatnak. A legegyszerűbb űrlap egy tartományt határoz meg. Létrehozhat például egy sorozatot, seq { 1 .. 5 }
amely öt elemet tartalmaz, köztük az 1. és az 5. végpontot. Két dupla időszak közötti növekményt (vagy decrementet) is megadhat. A következő kód például a 10 többszöröseinek sorozatát hozza létre.
// Sequence that has an increment.
seq { 0..10..100 }
A szekvenciakifejezések olyan F#-kifejezésekből állnak, amelyek a sorozat értékeit állítják elő. Az értékeket programozott módon is létrehozhatja:
seq { for i in 1..10 -> i * i }
Az előző minta az operátort ->
használja, amely lehetővé teszi egy olyan kifejezés megadását, amelynek értéke a sorozat részévé válik. Csak akkor használható ->
, ha az azt követő kód minden része értéket ad vissza.
Másik lehetőségként megadhatja a do
kulcsszót a következő választható lehetőségekkel yield
:
seq {
for i in 1..10 do
yield i * i
}
// The 'yield' is implicit and doesn't need to be specified in most cases.
seq {
for i in 1..10 do
i * i
}
Az alábbi kód a koordinátapárok listáját, valamint egy indexet hoz létre a rácsot jelképező tömbbe. Vegye figyelembe, hogy az első for
kifejezés megadása kötelező do
.
let (height, width) = (10, 10)
seq {
for row in 0 .. width - 1 do
for col in 0 .. height - 1 -> (row, col, row * width + col)
}
A if
sorozatban használt kifejezés egy szűrő. Ha például csak prímszámok sorozatát szeretné létrehozni, feltéve, hogy rendelkezik típusfüggvénysel isprime
int -> bool
, az alábbiak szerint hozza létre a sorozatot.
seq {
for n in 1..100 do
if isprime n then
n
}
Ahogy korábban említettük, itt kötelező megadni, do
mert nincs else
olyan ág, amely a if
. Ha megpróbál használni ->
, hibaüzenet jelenik meg, amely szerint nem minden ág ad vissza értéket.
A yield!
kulcsszó
Néha előfordulhat, hogy elemek sorozatát szeretné beilleszteni egy másik sorozatba. Ha egy sorozatot egy másik sorozatba szeretne belefoglalni, a kulcsszót kell használnia yield!
:
// Repeats '1 2 3 4 5' ten times
seq {
for _ in 1..10 do
yield! seq { 1; 2; 3; 4; 5}
}
Egy másik gondolkodásmód yield!
az, hogy simít egy belső sorozat, majd magában foglalja, hogy a tartalmazó sorozat.
Ha yield!
kifejezésben használják, minden más értéknek a kulcsszót kell használnia yield
:
// Combine repeated values with their values
seq {
for x in 1..10 do
yield x
yield! seq { for i in 1..x -> i}
}
Az előző példa az összes érték mellett az egyes x
értékek 1
x
értékét x
is létrehozza.
Példák
Az első példa egy sorozatkifejezést használ, amely egy iterációt, egy szűrőt és egy hozamot tartalmaz egy tömb létrehozásához. Ez a kód 1 és 100 közötti prímszámok sorozatát nyomtatja ki a konzolra.
// Recursive isprime function.
let isprime n =
let rec check i =
i > n / 2 || (n % i <> 0 && check (i + 1))
check 2
let aSequence =
seq {
for n in 1..100 do
if isprime n then
n
}
for x in aSequence do
printfn "%d" x
Az alábbi példa egy szorzási táblát hoz létre, amely három elemből áll, amelyek mindegyike két tényezőből és a termékből áll:
let multiplicationTable =
seq {
for i in 1..9 do
for j in 1..9 -> (i, j, i * j)
}
Az alábbi példa bemutatja, hogy az yield!
egyes sorozatokat egyetlen végső sorozatba kell egyesíteni. Ebben az esetben a bináris fa egyes részhalmazainak szekvenciái összefűződnek egy rekurzív függvényben a végső sorozat létrehozásához.
// Yield the values of a binary tree in a sequence.
type Tree<'a> =
| Tree of 'a * Tree<'a> * Tree<'a>
| Leaf of 'a
// inorder : Tree<'a> -> seq<'a>
let rec inorder tree =
seq {
match tree with
| Tree(x, left, right) ->
yield! inorder left
yield x
yield! inorder right
| Leaf x -> yield x
}
let mytree = Tree(6, Tree(2, Leaf(1), Leaf(3)), Leaf(9))
let seq1 = inorder mytree
printfn "%A" seq1
Sorozatok használata
A sorozatok számos olyan függvényt támogatnak, mint a listák. A szekvenciák olyan műveleteket is támogatnak, mint a csoportosítás és a számolás kulcsgeneráló függvények használatával. A szekvenciák az alhálózatok kinyerése szempontjából is változatosabb függvényeket támogatnak.
Számos adattípus, például listák, tömbök, halmazok és térképek implicit módon sorozatok, mivel ezek számba vett gyűjtemények. Az argumentumként szekvenciát használó függvények a gyakran használt F# adattípusok bármelyikével működnek, a implementálandó System.Collections.Generic.IEnumerable<'T>
.NET-adattípusokon kívül. Ezt egy olyan függvényhez hasonlítja, amely argumentumként egy listát vesz fel, amely csak listákat vehet fel. A típus seq<'T>
a típus rövidítése IEnumerable<'T>
. Ez azt jelenti, hogy minden olyan típus, amely az általános System.Collections.Generic.IEnumerable<'T>
típust implementálja , beleértve a tömböket, listákat, készleteket és térképeket az F#-ban, valamint a legtöbb .NET-gyűjteménytípust, kompatibilis a seq
típussal, és bárhol használható, ahol egy sorozat várható.
Modulfüggvények
Az FSharp.Collections névtér Seq moduljafüggvényeket tartalmaz a sorozatok kezeléséhez. Ezek a függvények listákkal, tömbökkel, térképekkel és halmazokkal is működnek, mivel ezek a típusok számba vehetők, ezért szekvenciákként is kezelhetők.
Sorozatok létrehozása
Sorozatokat a korábban ismertetett szekvenciakifejezések használatával vagy bizonyos függvények használatával hozhat létre.
Üres sorozatot a Seq.empty használatával hozhat létre, vagy létrehozhat egyetlen megadott elemet a Seq.singleton használatával.
let seqEmpty = Seq.empty
let seqOne = Seq.singleton 10
A Seq.init használatával létrehozhat egy sorozatot, amelyhez az elemek egy ön által megadott függvény használatával jönnek létre. A sorozat méretét is megadhatja. Ez a függvény ugyanúgy működik, mint a List.init, kivéve, hogy az elemek nem jönnek létre, amíg át nem halad a sorozaton. Az alábbi kód bemutatja a használatát Seq.init
.
let seqFirst5MultiplesOf10 = Seq.init 5 (fun n -> n * 10)
Seq.iter (fun elem -> printf "%d " elem) seqFirst5MultiplesOf10
A kimenet a következő:
0 10 20 30 40
A Seq.ofArray és a Seq.ofList'T>< függvény használatával tömbökből és listákból hozhat létre szekvenciákat. A tömböket és listákat azonban öntött operátorral szekvenciákká is konvertálhatja. Mindkét technika a következő kódban jelenik meg.
// Convert an array to a sequence by using a cast.
let seqFromArray1 = [| 1 .. 10 |] :> seq<int>
// Convert an array to a sequence by using Seq.ofArray.
let seqFromArray2 = [| 1 .. 10 |] |> Seq.ofArray
A Seq.cast használatával létrehozhat egy sorozatot egy gyengén beírt gyűjteményből, például a következőben definiált gyűjteménybőlSystem.Collections
. Az ilyen gyengén beírt gyűjtemények elemtípussal System.Object
rendelkeznek, és a nem általános System.Collections.Generic.IEnumerable`1
típus használatával vannak számba állítva. Az alábbi kód bemutatja, hogy egy Seq.cast
sorozatot kell átalakítani System.Collections.ArrayList
.
open System
let arr = ResizeArray<int>(10)
for i in 1 .. 10 do
arr.Add(10)
let seqCast = Seq.cast arr
Végtelen sorozatokat a Seq.initInfinite függvénnyel definiálhat. Egy ilyen sorozathoz olyan függvényt kell megadnia, amely minden elemet az elem indexéből hoz létre. A végtelen sorozatok a lusta kiértékelés miatt lehetségesek; az elemek szükség szerint jönnek létre a megadott függvény meghívásával. Az alábbi példakód a lebegőpontos számok végtelen sorozatát hozza létre, ebben az esetben az egymást követő egész számok négyzeteinek váltakozó sorozatát.
let seqInfinite =
Seq.initInfinite (fun index ->
let n = float (index + 1)
1.0 / (n * n * (if ((index + 1) % 2 = 0) then 1.0 else -1.0)))
printfn "%A" seqInfinite
A Seq.unfold egy olyan számítási függvényből hoz létre szekvenciát, amely egy állapotot vesz igénybe, és átalakítja a sorozat minden egyes elemének előállításához. Az állapot csak egy érték, amelyet az egyes elemek kiszámításához használnak, és az egyes elemek kiszámításakor változhatnak. A második argumentum a Seq.unfold
sorozat indításához használt kezdeti érték. Seq.unfold
Az állapothoz egy beállítástípust használ, amely lehetővé teszi a sorozat leállítását az None
érték visszaadásával. Az alábbi kód két példát mutat be a művelet által unfold
létrehozott szekvenciákra. seq1
fib
Az első, seq1
csak egy egyszerű sorozat, legfeljebb 20 számmal. A második a fib
Fibonacci-sorozat kiszámítására használható unfold
. Mivel a Fibonacci-sorozat minden eleme az előző két Fibonacci szám összege, az állapotérték egy rekord, amely a sorozat előző két számából áll. A kezdeti érték a (0,1)
sorozat első két száma.
let seq1 =
0 // Initial state
|> Seq.unfold (fun state ->
if (state > 20) then
None
else
Some(state, state + 1))
printfn "The sequence seq1 contains numbers from 0 to 20."
for x in seq1 do
printf "%d " x
let fib =
(0, 1)
|> Seq.unfold (fun state ->
let cur, next = state
if cur < 0 then // overflow
None
else
let next' = cur + next
let state' = next, next'
Some (cur, state') )
printfn "\nThe sequence fib contains Fibonacci numbers."
for x in fib do printf "%d " x
A kimenet a következő:
The sequence seq1 contains numbers from 0 to 20.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
The sequence fib contains Fibonacci numbers.
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181
Az alábbi kód egy példa, amely az itt ismertetett számos szekvenciamodul-függvényt használ a végtelen sorozatok értékeinek létrehozásához és kiszámításához. A kód futtatása eltarthat néhány percig.
// generateInfiniteSequence generates sequences of floating point
// numbers. The sequences generated are computed from the fDenominator
// function, which has the type (int -> float) and computes the
// denominator of each term in the sequence from the index of that
// term. The isAlternating parameter is true if the sequence has
// alternating signs.
let generateInfiniteSequence fDenominator isAlternating =
if (isAlternating) then
Seq.initInfinite (fun index ->
1.0 /(fDenominator index) * (if (index % 2 = 0) then -1.0 else 1.0))
else
Seq.initInfinite (fun index -> 1.0 /(fDenominator index))
// The harmonic alternating series is like the harmonic series
// except that it has alternating signs.
let harmonicAlternatingSeries = generateInfiniteSequence (fun index -> float index) true
// This is the series of reciprocals of the odd numbers.
let oddNumberSeries = generateInfiniteSequence (fun index -> float (2 * index - 1)) true
// This is the series of recipocals of the squares.
let squaresSeries = generateInfiniteSequence (fun index -> float (index * index)) false
// This function sums a sequence, up to the specified number of terms.
let sumSeq length sequence =
(0, 0.0)
|>
Seq.unfold (fun state ->
let subtotal = snd state + Seq.item (fst state + 1) sequence
if (fst state >= length) then
None
else
Some(subtotal, (fst state + 1, subtotal)))
// This function sums an infinite sequence up to a given value
// for the difference (epsilon) between subsequent terms,
// up to a maximum number of terms, whichever is reached first.
let infiniteSum infiniteSeq epsilon maxIteration =
infiniteSeq
|> sumSeq maxIteration
|> Seq.pairwise
|> Seq.takeWhile (fun elem -> abs (snd elem - fst elem) > epsilon)
|> List.ofSeq
|> List.rev
|> List.head
|> snd
// Compute the sums for three sequences that converge, and compare
// the sums to the expected theoretical values.
let result1 = infiniteSum harmonicAlternatingSeries 0.00001 100000
printfn "Result: %f ln2: %f" result1 (log 2.0)
let pi = Math.PI
let result2 = infiniteSum oddNumberSeries 0.00001 10000
printfn "Result: %f pi/4: %f" result2 (pi/4.0)
// Because this is not an alternating series, a much smaller epsilon
// value and more terms are needed to obtain an accurate result.
let result3 = infiniteSum squaresSeries 0.0000001 1000000
printfn "Result: %f pi*pi/6: %f" result3 (pi*pi/6.0)
Elemek keresése és keresése
A szekvenciák támogatják a listákkal elérhető funkciókat: Seq.exists, Seq.exists2, Seq.find, Seq.findIndex, Seq.pick, Seq.tryFind és Seq.tryFindIndex. Ezeknek a függvényeknek a szekvenciákhoz elérhető verziói csak a keresett elemig értékelik ki a sorozatot. Példák : Listák.
Alhálózatok beszerzése
A Seq.filter és a Seq.choose olyan, mint a listákhoz elérhető megfelelő függvények, azzal a kivételsel, hogy a szűrés és a kiválasztás csak a szekvenciaelemek kiértékeléséig történik.
A Seq.truncate egy másik sorozatból hoz létre egy sorozatot, de a sorozatot meghatározott számú elemre korlátozza. A Seq.take létrehoz egy új sorozatot, amely csak meghatározott számú elemet tartalmaz a sorozat kezdetétől kezdve. Ha a sorrendben kevesebb elem szerepel, mint amennyit meg szeretne adni, Seq.take
ad egy System.InvalidOperationException
. A különbség Seq.take
Seq.truncate
és az, hogy Seq.truncate
nem okoz hibát, ha az elemek száma kisebb, mint a megadott szám.
Az alábbi kód az és Seq.take
a kettő közötti Seq.truncate
viselkedést és különbségeket mutatja be.
let mySeq = seq { for i in 1 .. 10 -> i*i }
let truncatedSeq = Seq.truncate 5 mySeq
let takenSeq = Seq.take 5 mySeq
let truncatedSeq2 = Seq.truncate 20 mySeq
let takenSeq2 = Seq.take 20 mySeq
let printSeq seq1 = Seq.iter (printf "%A ") seq1; printfn ""
// Up to this point, the sequences are not evaluated.
// The following code causes the sequences to be evaluated.
truncatedSeq |> printSeq
truncatedSeq2 |> printSeq
takenSeq |> printSeq
// The following line produces a run-time error (in printSeq):
takenSeq2 |> printSeq
A kimenet a hiba bekövetkezése előtt a következő.
1 4 9 16 25
1 4 9 16 25 36 49 64 81 100
1 4 9 16 25
1 4 9 16 25 36 49 64 81 100
A Seq.takeWhile használatával megadhat egy predikátumfüggvényt (logikai függvényt), és létrehozhat egy sorozatot az eredeti sorozat azon elemeiből álló sorozatból, amelynek a predikátumát true
tartalmazza , de állítsa le azt az első elemet, amelynek a predikátum visszaadjafalse
. A Seq.skip egy olyan sorozatot ad vissza, amely kihagyja egy másik sorozat első elemeinek megadott számát, és visszaadja a fennmaradó elemeket. A Seq.skipWhile egy olyan sorozatot ad vissza, amely kihagyja egy másik sorozat első elemeit mindaddig, amíg a predikátum visszatér true
, majd visszaadja a fennmaradó elemeket, kezdve az első elemmel, amelynek a predikátuma visszaadja false
.
Az alábbi példakód bemutatja az , Seq.skip
és a közötti Seq.takeWhile
viselkedést és Seq.skipWhile
különbségeket.
// takeWhile
let mySeqLessThan10 = Seq.takeWhile (fun elem -> elem < 10) mySeq
mySeqLessThan10 |> printSeq
// skip
let mySeqSkipFirst5 = Seq.skip 5 mySeq
mySeqSkipFirst5 |> printSeq
// skipWhile
let mySeqSkipWhileLessThan10 = Seq.skipWhile (fun elem -> elem < 10) mySeq
mySeqSkipWhileLessThan10 |> printSeq
A kimenet a következő.
1 4 9
36 49 64 81 100
16 25 36 49 64 81 100
Sorozatok átalakítása
A Seq.pairwise egy új sorozatot hoz létre, amelyben a bemeneti sorozat egymást követő elemeit a rendszeruplákba csoportosítja.
let printSeq seq1 = Seq.iter (printf "%A ") seq1; printfn ""
let seqPairwise = Seq.pairwise (seq { for i in 1 .. 10 -> i*i })
printSeq seqPairwise
printfn ""
let seqDelta = Seq.map (fun elem -> snd elem - fst elem) seqPairwise
printSeq seqDelta
A Seq.windowed a következőhöz hasonlóSeq.pairwise
, azzal a kivételrel, hogy ahelyett, hogy sorozatot hoz létre, tömbök sorozatát állítja elő, amelyek a sorozat szomszédos elemeinek (ablakának) másolatait tartalmazzák. Az egyes tömbökben megadhatja a kívánt szomszédos elemek számát.
Az alábbi példakód bemutatja a használatát Seq.windowed
. Ebben az esetben az ablakban lévő elemek száma 3. A példa az előző kód példában definiált elemeket használja printSeq
.
let seqNumbers = [ 1.0; 1.5; 2.0; 1.5; 1.0; 1.5 ] :> seq<float>
let seqWindows = Seq.windowed 3 seqNumbers
let seqMovingAverage = Seq.map Array.average seqWindows
printfn "Initial sequence: "
printSeq seqNumbers
printfn "\nWindows of length 3: "
printSeq seqWindows
printfn "\nMoving average: "
printSeq seqMovingAverage
A kimenet a következő.
Kezdeti sorrend:
1.0 1.5 2.0 1.5 1.0 1.5
Windows of length 3:
[|1.0; 1.5; 2.0|] [|1.5; 2.0; 1.5|] [|2.0; 1.5; 1.0|] [|1.5; 1.0; 1.5|]
Moving average:
1.5 1.666666667 1.5 1.333333333
Műveletek több sorozattal
Seq.zip és Seq.zip3 két vagy három sorozatot, és létrehoz egy sorozatot a tuples. Ezek a függvények olyanok, mint a listákhoz elérhető megfelelő függvények. Nincs megfelelő funkció egy sorozat két vagy több sorozatra való elválasztásához. Ha szüksége van erre a funkcióra egy sorozathoz, konvertálja a sorozatot listává, és használja a List.unzip parancsot.
Rendezés, összehasonlítás és csoportosítás
A listákhoz támogatott rendezési függvények sorozatokkal is működnek. Ide tartozik a Seq.sort és a Seq.sortBy. Ezek a függvények végigvezetik az egész sorozatot.
Két sorozatot hasonlít össze a Seq.compareWith függvénnyel. A függvény egymás után összehasonlítja az egymást követő elemeket, és leáll, amikor az első egyenlőtlen párba ütközik. A további elemek nem járulnak hozzá az összehasonlításhoz.
Az alábbi kód a következő kód használatát Seq.compareWith
mutatja be.
let sequence1 = seq { 1 .. 10 }
let sequence2 = seq { 10 .. -1 .. 1 }
// Compare two sequences element by element.
let compareSequences =
Seq.compareWith (fun elem1 elem2 ->
if elem1 > elem2 then 1
elif elem1 < elem2 then -1
else 0)
let compareResult1 = compareSequences sequence1 sequence2
match compareResult1 with
| 1 -> printfn "Sequence1 is greater than sequence2."
| -1 -> printfn "Sequence1 is less than sequence2."
| 0 -> printfn "Sequence1 is equal to sequence2."
| _ -> failwith("Invalid comparison result.")
Az előző kódban csak az első elem lesz kiszámítva és megvizsgálva, az eredmény pedig -1.
A Seq.countBy egy függvényt vesz fel, amely minden elemhez létrehoz egy kulcsnak nevezett értéket. A rendszer minden elemhez létrehoz egy kulcsot a függvény meghívásával az egyes elemeken. Seq.countBy
ezután visszaad egy sorozatot, amely tartalmazza a kulcsértékeket, valamint a kulcs egyes értékeit létrehozó elemek számát.
let mySeq1 = seq { 1.. 100 }
let printSeq seq1 = Seq.iter (printf "%A ") seq1
let seqResult =
mySeq1
|> Seq.countBy (fun elem ->
if elem % 3 = 0 then 0
elif elem % 3 = 1 then 1
else 2)
printSeq seqResult
A kimenet a következő.
(1, 34) (2, 33) (0, 33)
Az előző kimenet azt mutatja, hogy az eredeti sorozat 34 eleme állította elő az 1. kulcsot, 33 értéket, amely a 2. kulcsot, és 33 értéket állított elő, amelyek a 0 kulcsot eredményezték.
A szekvenciák elemeit a Seq.groupBy meghívásával csoportosíthatja. Seq.groupBy
egy sorozatot és egy olyan függvényt vesz fel, amely egy elemet generál. A függvény végrehajtása a sorozat minden elemén történik. Seq.groupBy
a rekordok sorozatát adja vissza, ahol az egyes rekordok első eleme a kulcs, a második pedig a kulcsot előállító elemek sorozata.
Az alábbi példakód azt mutatja be, hogy az 1 és 100 közötti számok sorozatát három csoportba lehet particionálásra használni Seq.groupBy
, amelyek a 0, 1 és 2 különböző kulcsértékekkel rendelkeznek.
let sequence = seq { 1 .. 100 }
let printSeq seq1 = Seq.iter (printf "%A ") seq1
let sequences3 =
sequences
|> Seq.groupBy (fun index ->
if (index % 3 = 0) then 0
elif (index % 3 = 1) then 1
else 2)
sequences3 |> printSeq
A kimenet a következő.
(1, seq [1; 4; 7; 10; ...]) (2, seq [2; 5; 8; 11; ...]) (0, seq [3; 6; 9; 12; ...])
A Seq.distinct meghívásával létrehozhat egy sorozatot, amely kiküszöböli az ismétlődő elemeket. Vagy használhatja a Seq.distinctBy-t is, amely egy kulcsgeneráló függvényt hív meg az egyes elemeken. Az eredményként kapott sorozat az eredeti sorozat egyedi kulcsokkal rendelkező elemeit tartalmazza; a rendszer elveti azokat a későbbi elemeket, amelyek ismétlődő kulcsot hoznak létre egy korábbi elemhez.
Az alábbi példakód a következő kód használatát szemlélteti Seq.distinct
. Seq.distinct
bináris számokat ábrázoló sorozatok létrehozásával szemléltethető, majd azt mutatja, hogy az egyetlen különálló elem a 0 és az 1.
let binary n =
let rec generateBinary n =
if (n / 2 = 0) then [n]
else (n % 2) :: generateBinary (n / 2)
generateBinary n
|> List.rev
|> Seq.ofList
printfn "%A" (binary 1024)
let resultSequence = Seq.distinct (binary 1024)
printfn "%A" resultSequence
Az alábbi kód Seq.distinctBy
egy negatív és pozitív számokat tartalmazó sorozattal kezdődik, és az abszolút érték függvényt használja kulcsgeneráló függvényként. Az eredményül kapott sorozatból hiányzik a sorozat negatív számainak megfelelő összes pozitív szám, mivel a negatív számok a sorozat korábbi részében jelennek meg, ezért az azonos abszolút értékkel vagy kulccsal rendelkező pozitív számok helyett vannak kiválasztva.
let inputSequence = { -5 .. 10 }
let printSeq seq1 = Seq.iter (printf "%A ") seq1
printfn "Original sequence: "
printSeq inputSequence
printfn "\nSequence with distinct absolute values: "
let seqDistinctAbsoluteValue = Seq.distinctBy (fun elem -> abs elem) inputSequence
printSeq seqDistinctAbsoluteValue
Olvasási és gyorsítótárazott sorozatok
A Seq.readonly egy sorozat írásvédett másolatát hozza létre. Seq.readonly
akkor hasznos, ha írásvédett gyűjteménysel (például tömbbel) rendelkezik, és nem szeretné módosítani az eredeti gyűjteményt. Ez a függvény az adatbefoglalás megőrzésére használható. Az alábbi példakódban létrejön egy tömböt tartalmazó típus. A tulajdonság elérhetővé teszi a tömböt, de tömb visszaadása helyett a tömbből Seq.readonly
létrehozott sorozatot ad vissza.
type ArrayContainer(start, finish) =
let internalArray = [| start .. finish |]
member this.RangeSeq = Seq.readonly internalArray
member this.RangeArray = internalArray
let newArray = new ArrayContainer(1, 10)
let rangeSeq = newArray.RangeSeq
let rangeArray = newArray.RangeArray
// These lines produce an error:
//let myArray = rangeSeq :> int array
//myArray[0] <- 0
// The following line does not produce an error.
// It does not preserve encapsulation.
rangeArray[0] <- 0
A Seq.cache létrehoz egy szekvencia tárolt verzióját. A Seq.cache
szekvenciák újraértékelésének elkerülése érdekében, vagy ha több szál is használ egy sorozatot, de meg kell győződnie arról, hogy minden elem csak egy alkalommal működik. Ha több szál által használt sorozattal rendelkezik, egy olyan szálat használhat, amely számba fogja és kiszámítja az eredeti sorozat értékeit, a fennmaradó szálak pedig használhatják a gyorsítótárazott sorozatot.
Számítások végrehajtása sorozatokon
Az egyszerű aritmetikai műveletek olyanok, mint a listák, például a Seq.average, a Seq.sum, a Seq.averageBy, a Seq.sumBy stb.
A Seq.fold, a Seq.reduce és a Seq.scan hasonló a listákhoz elérhető függvényekhez. A sorozatok a támogatott függvények teljes változatainak egy részét támogatják. További információkért és példákért lásd a Listák című témakört.