Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Urutan adalah serangkaian elemen logis dari satu jenis. Urutan sangat berguna ketika Anda memiliki pengumpulan data yang besar dan diurutkan tetapi tidak selalu berharap untuk menggunakan semua elemen. Elemen urutan individu hanya dihitung sesuai kebutuhan, sehingga urutan dapat memberikan performa yang lebih baik daripada daftar dalam situasi di mana tidak semua elemen digunakan. Urutan diwakili oleh seq<'T> jenis , yang merupakan alias untuk IEnumerable<T>. Oleh karena itu, jenis .NET apa pun yang mengimplementasikan IEnumerable<T> antarmuka dapat digunakan sebagai urutan.
Modul Seq menyediakan dukungan untuk manipulasi yang melibatkan urutan.
Ekspresi Urutan
Ekspresi urutan adalah ekspresi yang mengevaluasi ke urutan. Ekspresi urutan dapat mengambil sejumlah formulir. Formulir paling sederhana menentukan rentang. Misalnya, seq { 1 .. 5 } membuat urutan yang berisi lima elemen, termasuk titik akhir 1 dan 5. Anda juga dapat menentukan kenaikan (atau penurunan) antara dua periode ganda. Misalnya, kode berikut membuat urutan kelipatan 10.
// Sequence that has an increment.
seq { 0..10..100 }
Ekspresi urutan terdiri dari ekspresi F# yang menghasilkan nilai urutan. Anda juga dapat menghasilkan nilai secara terprogram:
seq { for i in 1..10 -> i * i }
Sampel sebelumnya menggunakan -> operator, yang memungkinkan Anda menentukan ekspresi yang nilainya akan menjadi bagian dari urutan. Anda hanya dapat menggunakan -> jika setiap bagian kode yang mengikutinya mengembalikan nilai.
Atau, Anda dapat menentukan do kata kunci, dengan opsional yield yang mengikuti:
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
}
Kode berikut menghasilkan daftar pasangan koordinat bersama dengan indeks ke dalam array yang mewakili kisi. Perhatikan bahwa ekspresi pertama for memerlukan do untuk ditentukan.
let (height, width) = (10, 10)
seq {
for row in 0 .. width - 1 do
for col in 0 .. height - 1 -> (row, col, row * width + col)
}
Ekspresi if yang digunakan dalam urutan adalah filter. Misalnya, untuk menghasilkan urutan hanya bilangan prima, dengan asumsi Anda memiliki fungsi isprime jenis int -> bool, buat urutan sebagai berikut.
seq {
for n in 1..100 do
if isprime n then
n
}
Seperti disebutkan sebelumnya, do diperlukan di sini karena tidak else ada cabang yang mengikuti if. Jika Anda mencoba menggunakan ->, Anda akan mendapatkan kesalahan yang mengatakan bahwa tidak semua cabang mengembalikan nilai.
Kata kunci yield!
Terkadang, Anda mungkin ingin memasukkan urutan elemen ke dalam urutan lain. Untuk menyertakan urutan dalam urutan lain, Anda harus menggunakan yield! kata kunci:
// Repeats '1 2 3 4 5' ten times
seq {
for _ in 1..10 do
yield! seq { 1; 2; 3; 4; 5}
}
Cara berpikir yield! lain adalah meratakan urutan dalam dan kemudian mencakupnya dalam urutan yang mengandung.
Ketika yield! digunakan dalam ekspresi, semua nilai tunggal lainnya harus menggunakan yield kata kunci:
// Combine repeated values with their values
seq {
for x in 1..10 do
yield x
yield! seq { for i in 1..x -> i}
}
Contoh sebelumnya akan menghasilkan nilai x selain semua nilai dari 1 ke x untuk setiap x.
Contoh
Contoh pertama menggunakan ekspresi urutan yang berisi iterasi, filter, dan hasil untuk menghasilkan array. Kode ini mencetak urutan angka utama antara 1 dan 100 ke konsol.
// 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
Contoh berikut membuat tabel perkalian yang terdiri dari tuple tiga elemen, masing-masing terdiri dari dua faktor dan produk:
let multiplicationTable =
seq {
for i in 1..9 do
for j in 1..9 -> (i, j, i * j)
}
Contoh berikut menunjukkan penggunaan yield! untuk menggabungkan urutan individual ke dalam satu urutan akhir. Dalam hal ini, urutan untuk setiap subtree dalam pohon biner digabungkan dalam fungsi rekursif untuk menghasilkan urutan akhir.
// 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
Menggunakan Urutan
Urutan mendukung banyak fungsi yang sama dengan daftar. Urutan juga mendukung operasi seperti pengelompokan dan penghitungan dengan menggunakan fungsi pembuatan kunci. Urutan juga mendukung fungsi yang lebih beragam untuk mengekstrak subur.
Banyak jenis data, seperti daftar, array, set, dan peta secara implisit berurutan karena merupakan koleksi yang dapat dijumlahkan. Fungsi yang mengambil urutan sebagai argumen berfungsi dengan salah satu jenis data F# umum, selain jenis data .NET apa pun yang mengimplementasikan System.Collections.Generic.IEnumerable<'T>. Kontras ini dengan fungsi yang mengambil daftar sebagai argumen, yang hanya dapat mengambil daftar. Jenisnya seq<'T> adalah singkatan jenis untuk IEnumerable<'T>. Ini berarti bahwa setiap jenis yang mengimplementasikan generik System.Collections.Generic.IEnumerable<'T>, yang mencakup array, daftar, set, dan peta di F#, dan juga sebagian besar jenis koleksi .NET, kompatibel dengan seq jenis dan dapat digunakan di mana pun urutan diharapkan.
Fungsi Modul
Modul Seq di namespace layanan FSharp.Collections berisi fungsi untuk bekerja dengan urutan. Fungsi-fungsi ini bekerja dengan daftar, array, peta, dan set juga, karena semua jenis tersebut dapat dijumlahkan, dan oleh karena itu dapat diperlakukan sebagai urutan.
Membuat Urutan
Anda dapat membuat urutan dengan menggunakan ekspresi urutan, seperti yang dijelaskan sebelumnya, atau dengan menggunakan fungsi tertentu.
Anda dapat membuat urutan kosong dengan menggunakan Seq.empty, atau Anda dapat membuat urutan hanya satu elemen yang ditentukan dengan menggunakan Seq.singleton.
let seqEmpty = Seq.empty
let seqOne = Seq.singleton 10
Anda dapat menggunakan Seq.init untuk membuat urutan yang elemennya dibuat dengan menggunakan fungsi yang Anda sediakan. Anda juga menyediakan ukuran untuk urutannya. Fungsi ini sama seperti List.init, kecuali bahwa elemen tidak dibuat sampai Anda melakukan iterasi melalui urutan. Kode berikut mengilustrasikan penggunaan Seq.init.
let seqFirst5MultiplesOf10 = Seq.init 5 (fun n -> n * 10)
Seq.iter (fun elem -> printf "%d " elem) seqFirst5MultiplesOf10
Outputnya adalah
0 10 20 30 40
Dengan menggunakan Fungsi Seq.ofArray dan Seq.ofList'T<>, Anda dapat membuat urutan dari array dan daftar. Namun, Anda juga dapat mengonversi array dan daftar menjadi urutan dengan menggunakan operator cast. Kedua teknik ditunjukkan dalam kode berikut.
// 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
Dengan menggunakan Seq.cast, Anda dapat membuat urutan dari koleksi yang diketik dengan lemah, seperti yang didefinisikan dalam System.Collections. Koleksi yang ditik lemah tersebut memiliki jenis System.Object elemen dan dijumlahkan dengan menggunakan jenis non-generik System.Collections.Generic.IEnumerable`1 . Kode berikut mengilustrasikan penggunaan Seq.cast untuk mengonversi System.Collections.ArrayList menjadi urutan.
open System
let arr = ResizeArray<int>(10)
for i in 1 .. 10 do
arr.Add(10)
let seqCast = Seq.cast arr
Anda dapat menentukan urutan tak terbatas dengan menggunakan fungsi Seq.initInfinite . Untuk urutan seperti itu, Anda menyediakan fungsi yang menghasilkan setiap elemen dari indeks elemen. Urutan tak terbatas dimungkinkan karena evaluasi malas; elemen dibuat sesuai kebutuhan dengan memanggil fungsi yang Anda tentukan. Contoh kode berikut menghasilkan urutan angka titik mengambang yang tak terbatas, dalam hal ini rangkaian timbal balik bolak-balik bilangan bulat berturut-turut.
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
Seq.unfold menghasilkan urutan dari fungsi komputasi yang mengambil status dan mengubahnya untuk menghasilkan setiap elemen berikutnya dalam urutan. Status hanyalah nilai yang digunakan untuk menghitung setiap elemen, dan dapat berubah saat setiap elemen dihitung. Argumen kedua adalah Seq.unfold nilai awal yang digunakan untuk memulai urutan.
Seq.unfold menggunakan jenis opsi untuk status , yang memungkinkan Anda mengakhiri urutan dengan mengembalikan None nilai . Kode berikut menunjukkan dua contoh urutan, seq1 dan fib, yang dihasilkan oleh unfold operasi. Yang pertama, seq1, hanyalah urutan sederhana dengan angka hingga 20. Yang kedua, fib, menggunakan unfold untuk menghitung urutan Fibonacci. Karena setiap elemen dalam urutan Fibonacci adalah jumlah dari dua angka Fibonacci sebelumnya, nilai status adalah tuple yang terdiri dari dua angka sebelumnya dalam urutan. Nilai awal adalah (0,1), dua angka pertama dalam urutan.
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
Outputnya adalah sebagai berikut:
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
Kode berikut adalah contoh yang menggunakan banyak fungsi modul urutan yang dijelaskan di sini untuk menghasilkan dan menghitung nilai urutan tak terbatas. Kode mungkin memerlukan waktu beberapa menit untuk dijalankan.
// 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 =
sequence
|> Seq.skip 1 // skip first item (matching the original behavior)
|> Seq.truncate length // don't take more than length items
|> Seq.scan (+) 0.0 // generate running sums
|> Seq.skip 1 // skip the initial 0.0 from sequence of running sums
// 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)
Mencari dan Menemukan Elemen
Sequences mendukung fungsionalitas yang tersedia dengan daftar: Seq.exists, Seq.exists2, Seq.find, Seq.findIndex, Seq.pick, Seq.tryFind, dan Seq.tryFindIndex. Versi fungsi-fungsi ini yang tersedia untuk urutan mengevaluasi urutan hanya hingga elemen yang sedang dicari. Misalnya, lihat Daftar.
Mendapatkan Sub-urutan
Seq.filter dan Seq.choose seperti fungsi terkait yang tersedia untuk daftar, kecuali bahwa pemfilteran dan pemilihan tidak terjadi sampai elemen urutan dievaluasi.
Seq.truncate membuat urutan dari urutan lain, tetapi membatasi urutan ke jumlah elemen yang ditentukan.
Seq.take membuat urutan baru yang hanya berisi sejumlah elemen tertentu dari awal urutan. Jika ada lebih sedikit elemen dalam urutan daripada yang Anda tentukan untuk diambil, Seq.take melemparkan System.InvalidOperationException. Perbedaan antara Seq.take dan Seq.truncate adalah bahwa tidak menghasilkan kesalahan jika jumlah elemen lebih sedikit dari angka yang Seq.truncate Anda tentukan.
Kode berikut menunjukkan perilaku dan perbedaan antara Seq.truncate dan Seq.take.
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
Output, sebelum kesalahan terjadi, adalah sebagai berikut.
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
Dengan menggunakan Seq.takeWhile, Anda dapat menentukan fungsi predikat (fungsi Boolean) dan membuat urutan dari urutan lain yang terdiri dari elemen-elemen urutan asli yang predikatnya adalah true, tetapi berhenti sebelum elemen pertama yang predikatnya mengembalikan false.
Seq.skip mengembalikan urutan yang melewati jumlah tertentu dari elemen pertama dari urutan lain dan mengembalikan elemen yang tersisa.
Seq.skipWhile mengembalikan urutan yang melewati elemen pertama dari urutan lain selama predikat mengembalikan true, lalu mengembalikan elemen yang tersisa, dimulai dengan elemen pertama yang predikatnya mengembalikan false.
Contoh kode berikut mengilustrasikan perilaku dan perbedaan antara Seq.takeWhile, , Seq.skipdan Seq.skipWhile.
// 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
Outputnya sebagai berikut.
1 4 9
36 49 64 81 100
16 25 36 49 64 81 100
Mengubah Urutan
Seq.pairwise menciptakan urutan baru di mana elemen berturut-turut dari urutan input dikelompokkan menjadi tuple.
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
Seq.windowed seperti Seq.pairwise, kecuali bahwa alih-alih menghasilkan urutan tuple, itu menghasilkan urutan array yang berisi salinan elemen yang berdekatan ( jendela) dari urutan. Anda menentukan jumlah elemen yang berdekatan yang Anda inginkan di setiap array.
Contoh kode berikut menunjukkan penggunaan Seq.windowed. Dalam hal ini jumlah elemen di jendela adalah 3. Contoh menggunakan printSeq, yang didefinisikan dalam contoh kode sebelumnya.
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
Outputnya sebagai berikut.
Urutan awal:
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
Operasi dengan Beberapa Urutan
Seq.zip dan Seq.zip3 mengambil dua atau tiga urutan dan menghasilkan urutan tuple. Fungsi-fungsi ini seperti fungsi yang sesuai yang tersedia untuk daftar. Tidak ada fungsionalitas yang sesuai untuk memisahkan satu urutan menjadi dua urutan atau lebih. Jika Anda memerlukan fungsionalitas ini untuk urutan, konversi urutan ke daftar dan gunakan List.unzip.
Mengurutkan, Membandingkan, dan Mengelompokkan
Fungsi pengurutan yang didukung untuk daftar juga berfungsi dengan urutan. Ini termasuk Seq.sort dan Seq.sortBy. Fungsi-fungsi ini melakukan iterasi melalui seluruh urutan.
Anda membandingkan dua urutan dengan menggunakan fungsi Seq.compareWith . Fungsi ini membandingkan elemen berturut-turut, dan berhenti ketika menemukan pasangan tidak sama pertama. Elemen tambahan apa pun tidak berkontribusi pada perbandingan.
Kode berikut menunjukkan penggunaan Seq.compareWith.
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.")
Dalam kode sebelumnya, hanya elemen pertama yang dihitung dan diperiksa, dan hasilnya adalah -1.
Seq.countBy mengambil fungsi yang menghasilkan nilai yang disebut kunci untuk setiap elemen. Kunci dihasilkan untuk setiap elemen dengan memanggil fungsi ini pada setiap elemen.
Seq.countBy kemudian mengembalikan urutan yang berisi nilai kunci, dan hitungan jumlah elemen yang menghasilkan setiap nilai kunci.
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
Outputnya sebagai berikut.
(1, 34) (2, 33) (0, 33)
Output sebelumnya menunjukkan bahwa ada 34 elemen dari urutan asli yang menghasilkan nilai kunci 1, 33 yang menghasilkan nilai kunci 2, dan 33 yang menghasilkan kunci 0.
Anda dapat mengelompokkan elemen urutan dengan memanggil Seq.groupBy.
Seq.groupBy mengambil urutan dan fungsi yang menghasilkan kunci dari elemen. Fungsi dijalankan pada setiap elemen urutan.
Seq.groupBy mengembalikan urutan tuple, di mana elemen pertama dari setiap tuple adalah kunci dan yang kedua adalah urutan elemen yang menghasilkan kunci tersebut.
Contoh kode berikut menunjukkan penggunaan Seq.groupBy untuk mempartisi urutan angka dari 1 hingga 100 menjadi tiga grup yang memiliki nilai kunci berbeda 0, 1, dan 2.
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
Outputnya sebagai berikut.
(1, seq [1; 4; 7; 10; ...]) (2, seq [2; 5; 8; 11; ...]) (0, seq [3; 6; 9; 12; ...])
Anda dapat membuat urutan yang menghilangkan elemen duplikat dengan memanggil Seq.distinct. Atau Anda dapat menggunakan Seq.distinctBy, yang mengambil fungsi pembuatan kunci untuk dipanggil pada setiap elemen. Urutan yang dihasilkan berisi elemen urutan asli yang memiliki kunci unik; elemen selanjutnya yang menghasilkan kunci duplikat ke elemen sebelumnya dibuang.
Contoh kode berikut mengilustrasikan penggunaan Seq.distinct.
Seq.distinct ditunjukkan dengan menghasilkan urutan yang mewakili angka biner, dan kemudian menunjukkan bahwa satu-satunya elemen yang berbeda adalah 0 dan 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
Kode berikut menunjukkan Seq.distinctBy dengan memulai dengan urutan yang berisi angka negatif dan positif dan menggunakan fungsi nilai absolut sebagai fungsi pembuatan kunci. Urutan yang dihasilkan kehilangan semua angka positif yang sesuai dengan angka negatif dalam urutan, karena angka negatif muncul sebelumnya dalam urutan dan oleh karena itu dipilih alih-alih angka positif yang memiliki nilai absolut yang sama, atau kunci.
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
Urutan Readonly dan Cache
Seq.readonly membuat salinan urutan baca-saja.
Seq.readonly berguna ketika Anda memiliki koleksi baca-tulis, seperti array, dan Anda tidak ingin mengubah koleksi asli. Fungsi ini dapat digunakan untuk mempertahankan enkapsulasi data. Dalam contoh kode berikut, jenis yang berisi array dibuat. Properti mengekspos array, tetapi alih-alih mengembalikan array, properti mengembalikan urutan yang dibuat dari array dengan menggunakan Seq.readonly.
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
Seq.cache membuat versi urutan yang disimpan. Gunakan Seq.cache untuk menghindari evaluasi ulang urutan, atau ketika Anda memiliki beberapa utas yang menggunakan urutan, tetapi Anda harus memastikan bahwa setiap elemen hanya ditindaklanjuti satu kali. Ketika Anda memiliki urutan yang sedang digunakan oleh beberapa utas, Anda dapat memiliki satu utas yang menghitung dan menghitung nilai untuk urutan asli, dan utas yang tersisa dapat menggunakan urutan cache.
Melakukan Komputasi pada Urutan
Operasi aritmatika sederhana seperti daftar, seperti Seq.average, Seq.sum, Seq.averageBy, Seq.sumBy, dan sebagainya.
Seq.fold, Seq.reduce, dan Seq.scan seperti fungsi terkait yang tersedia untuk daftar. Urutan mendukung subset variasi lengkap fungsi ini yang mencantumkan dukungan. Untuk informasi dan contoh selengkapnya, lihat Daftar.