Listeler
F# içindeki bir liste, aynı türde sıralı, sabit bir öğe serisidir. Listelerde temel işlemleri gerçekleştirmek için Liste modülündeki işlevleri kullanın.
Liste Oluşturma ve Başlatma
Aşağıdaki kod satırında gösterildiği gibi, öğeleri noktalı virgülle ayırıp köşeli ayraç içine alarak açıkça listeleyerek liste tanımlayabilirsiniz.
let list123 = [ 1; 2; 3 ]
Ayrıca öğeler arasına satır sonları koyabilirsiniz. Bu durumda noktalı virgüller isteğe bağlıdır. İkinci söz dizimi, öğe başlatma ifadeleri daha uzun olduğunda veya her öğe için bir açıklama eklemek istediğinizde daha okunabilir kodla sonuçlanabilir.
let list123 = [ 1; 2; 3 ]
Normalde, tüm liste öğeleri aynı türde olmalıdır. Bir özel durum, öğelerin temel tür olarak belirtildiği bir listenin türetilmiş türlerdeki öğelere sahip olmasıdır. Bu nedenle, hem hem de Button
CheckBox
türetildiğinden Control
aşağıdakiler kabul edilebilir.
let myControlList: Control list = [ new Button(); new CheckBox() ]
Liste öğelerini, aşağıdaki kodda gösterildiği gibi aralık işleci ()..
ile ayrılmış tamsayılarla belirtilen bir aralık kullanarak da tanımlayabilirsiniz.
let list1 = [ 1..10 ]
Boş bir liste, aralarında hiçbir şey olmayan bir çift köşeli ayraç tarafından belirtilir.
// An empty list.
let listEmpty = []
Liste oluşturmak için bir sıra ifadesi de kullanabilirsiniz. Daha fazla bilgi için bkz . Sıralı İfadeler . Örneğin, aşağıdaki kod 1 ile 10 arasını içeren tamsayı karelerinin listesini oluşturur.
let listOfSquares = [ for i in 1..10 -> i * i ]
Listelerle Çalışma İşleçleri
(eksiler) işlecini ::
kullanarak bir listeye öğe ekleyebilirsiniz. ise list1
[2; 3; 4]
, aşağıdaki kod olarak [100; 2; 3; 4]
oluştururlist2
.
let list2 = 100 :: list1
Aşağıdaki kodda olduğu gibi işlecini @
kullanarak uyumlu türleri olan listeleri birleştirebilirsiniz. ve list1
ise [2; 3; 4]
list2
[100; 2; 3; 4]
, bu kod olarak [2; 3; 4; 100; 2; 3; 4]
oluşturur.list3
let list3 = list1 @ list2
Listelerde işlem gerçekleştirme işlevleri Liste modülünde bulunur.
F# içindeki listeler sabit olduğundan, değiştirme işlemleri var olan listeleri değiştirmek yerine yeni listeler oluşturur.
F# içindeki listeler tek bağlantılı listeler olarak uygulanır; bu da yalnızca listenin başına erişen işlemlerin O(1) olduğu ve öğe erişiminin O(n) olduğu anlamına gelir.
Properties
Liste türü aşağıdaki özellikleri destekler:
Özellik | Türü | Açıklama |
---|---|---|
Kafa | 'T |
İlk öğe. |
Boş | 'T list |
Uygun türde boş bir liste döndüren statik özellik. |
IsEmpty | bool |
true listede öğe yoksa. |
Kalem | 'T |
Belirtilen dizindeki öğe (sıfır tabanlı). |
Uzunluk | int |
Öğe sayısı. |
Kuyruk | 'T list |
İlk öğesi olmayan liste. |
Bu özelliklerin kullanımına bazı örnekler aşağıda verilmiştir.
let list1 = [ 1; 2; 3 ]
// Properties
printfn "list1.IsEmpty is %b" (list1.IsEmpty)
printfn "list1.Length is %d" (list1.Length)
printfn "list1.Head is %d" (list1.Head)
printfn "list1.Tail.Head is %d" (list1.Tail.Head)
printfn "list1.Tail.Tail.Head is %d" (list1.Tail.Tail.Head)
printfn "list1.Item(1) is %d" (list1.Item(1))
Listeleri Kullanma
Listelerle programlama, az miktarda kodla karmaşık işlemler gerçekleştirmenizi sağlar. Bu bölümde, işlevsel programlama için önemli olan listelerdeki yaygın işlemler açıklanmaktadır.
Listelerle Özyineleme
Listeler özyinelemeli programlama teknikleri için benzersiz olarak uygundur. Listenin her öğesinde gerçekleştirilmesi gereken bir işlemi düşünün. Bunu yinelemeli olarak, listenin başında çalışarak ve ardından ilk öğe olmadan özgün listeden oluşan daha küçük bir liste olan listenin kuyruğunu bir sonraki özyineleme düzeyine geri geçirerek yapabilirsiniz.
Böyle bir özyinelemeli işlev yazmak için, bir listenin başını kuyruktan ayırmanızı sağlayan desen eşleştirmesinde eksi işlecini (::
) kullanırsınız.
Aşağıdaki kod örneği, bir listede işlem gerçekleştiren özyinelemeli bir işlev uygulamak için desen eşleştirmenin nasıl kullanılacağını gösterir.
let rec sum list =
match list with
| head :: tail -> head + sum tail
| [] -> 0
Önceki kod küçük listeler için iyi çalışır, ancak daha büyük listeler için yığın taşabilir. Aşağıdaki kod, özyinelemeli işlevlerle çalışmaya yönelik standart bir teknik olan bir biriktirici bağımsız değişkeni kullanarak bu kodu geliştirir. Akümülatör bağımsız değişkeninin kullanılması, işlev kuyruğunun özyinelemeli olmasını sağlar ve bu da yığın alanından tasarruf sağlar.
let sum list =
let rec loop list acc =
match list with
| head :: tail -> loop tail (acc + head)
| [] -> acc
loop list 0
işlevi RemoveAllMultiples
, iki liste alan özyinelemeli bir işlevdir. İlk liste, katları kaldırılacak sayıları içerir ve ikinci liste de sayıların kaldırılacağı listedir. Aşağıdaki örnekteki kod bu özyinelemeli işlevi kullanarak bir listedeki asal olmayan tüm sayıları ortadan kaldırır ve sonuç olarak asal sayıların listesini bırakır.
let IsPrimeMultipleTest n x = x = n || x % n <> 0
let rec RemoveAllMultiples listn listx =
match listn with
| head :: tail -> RemoveAllMultiples tail (List.filter (IsPrimeMultipleTest head) listx)
| [] -> listx
let GetPrimesUpTo n =
let max = int (sqrt (float n))
RemoveAllMultiples [ 2..max ] [ 1..n ]
printfn "Primes Up To %d:\n %A" 100 (GetPrimesUpTo 100)
Çıktı aşağıdaki şekilde olacaktır:
Primes Up To 100:
[2; 3; 5; 7; 11; 13; 17; 19; 23; 29; 31; 37; 41; 43; 47; 53; 59; 61; 67; 71; 73; 79; 83; 89; 97]
Modül İşlevleri
Liste modülü, bir listenin öğelerine erişen işlevler sağlar. Head öğesi, erişimi en hızlı ve en kolay öğedir. Head özelliğini veya List.head modül işlevini kullanın. Tail özelliğini veya List.tail işlevini kullanarak listenin kuyruğuna erişebilirsiniz. Dizine göre bir öğe bulmak için List.nth işlevini kullanın. List.nth
listeden çapraz geçişler. Bu nedenle, O(n). Kodunuz sık kullanıyorsa List.nth
, liste yerine dizi kullanmayı düşünebilirsiniz. Dizilerdeki öğe erişimi O(1) değeridir.
Listelerde Boole İşlemleri
List.isEmpty işlevi, bir listenin herhangi bir öğesi olup olmadığını belirler.
List.exists işlevi bir listenin öğelerine Boole testi uygular ve herhangi bir öğe testi karşılarsa döndürürtrue
. List.exists2 benzerdir ancak iki listede birbirini izleyen öğe çiftleri üzerinde çalışır.
Aşağıdaki kod, kullanımını List.exists
gösterir.
// Use List.exists to determine whether there is an element of a list satisfies a given Boolean expression.
// containsNumber returns true if any of the elements of the supplied list match
// the supplied number.
let containsNumber number list = List.exists (fun elem -> elem = number) list
let list0to3 = [0 .. 3]
printfn "For list %A, contains zero is %b" list0to3 (containsNumber 0 list0to3)
Çıktı aşağıdaki şekilde olacaktır:
For list [0; 1; 2; 3], contains zero is true
Aşağıdaki örnekte kullanımı gösterilmektedir List.exists2
.
// Use List.exists2 to compare elements in two lists.
// isEqualElement returns true if any elements at the same position in two supplied
// lists match.
let isEqualElement list1 list2 = List.exists2 (fun elem1 elem2 -> elem1 = elem2) list1 list2
let list1to5 = [ 1 .. 5 ]
let list5to1 = [ 5 .. -1 .. 1 ]
if (isEqualElement list1to5 list5to1) then
printfn "Lists %A and %A have at least one equal element at the same position." list1to5 list5to1
else
printfn "Lists %A and %A do not have an equal element at the same position." list1to5 list5to1
Çıktı aşağıdaki şekilde olacaktır:
Lists [1; 2; 3; 4; 5] and [5; 4; 3; 2; 1] have at least one equal element at the same position.
Listenin tüm öğelerinin bir koşulu karşılayıp karşılamadığını test etmek istiyorsanız List.forall kullanabilirsiniz.
let isAllZeroes list = List.forall (fun elem -> elem = 0.0) list
printfn "%b" (isAllZeroes [0.0; 0.0])
printfn "%b" (isAllZeroes [0.0; 1.0])
Çıktı aşağıdaki şekilde olacaktır:
true
false
Benzer şekilde, List.forall2 , iki listedeki ilgili konumlardaki tüm öğelerin her öğe çiftini içeren bir Boole ifadesini karşılayıp karşılamadığını belirler.
let listEqual list1 list2 = List.forall2 (fun elem1 elem2 -> elem1 = elem2) list1 list2
printfn "%b" (listEqual [0; 1; 2] [0; 1; 2])
printfn "%b" (listEqual [0; 0; 0] [0; 1; 0])
Çıktı aşağıdaki şekilde olacaktır:
true
false
Listelerde Sıralama İşlemleri
List.sort, List.sortBy ve List.sortWith işlevleri listeleri sıralar. Sıralama işlevi, bu üç işlevden hangisinin kullanılacağını belirler. List.sort
varsayılan genel karşılaştırmayı kullanır. Genel karşılaştırma, değerleri karşılaştırmak için genel karşılaştırma işlevini temel alan genel işleçleri kullanır. Basit sayısal türler, tanımlama kümeleri, kayıtlar, ayrımcı birleşimler, listeler, diziler ve uygulayan System.IComparable
herhangi bir tür gibi çok çeşitli öğe türleriyle verimli bir şekilde çalışır. uygulayan System.IComparable
türler için genel karşılaştırma işlevi System.IComparable.CompareTo()
kullanır. Genel karşılaştırma dizelerle de çalışır, ancak kültürden bağımsız bir sıralama düzeni kullanır. İşlev türleri gibi desteklenmeyen türlerde genel karşılaştırma kullanılmamalıdır. Ayrıca, varsayılan genel karşılaştırmanın performansı küçük yapılandırılmış türler için en iyisidir; sık karşılaştırılması ve sıralanması gereken daha büyük yapılandırılmış türler için yöntemi verimli bir şekilde uygulamayı System.IComparable
ve sağlamayı System.IComparable.CompareTo()
göz önünde bulundurun.
List.sortBy
sıralama ölçütü olarak kullanılan bir değer döndüren bir işlev alır ve List.sortWith
bir karşılaştırma işlevini bağımsız değişken olarak alır. Bu ikinci iki işlev, karşılaştırmayı desteklemeyen türlerle çalışırken veya kültüre duyarlı dizelerde olduğu gibi karşılaştırma daha karmaşık karşılaştırma semantiği gerektirdiğinde yararlıdır.
Aşağıdaki örnekte kullanımı gösterilmektedir List.sort
.
let sortedList1 = List.sort [1; 4; 8; -2; 5]
printfn "%A" sortedList1
Çıktı aşağıdaki şekilde olacaktır:
[-2; 1; 4; 5; 8]
Aşağıdaki örnekte kullanımı gösterilmektedir List.sortBy
.
let sortedList2 = List.sortBy (fun elem -> abs elem) [1; 4; 8; -2; 5]
printfn "%A" sortedList2
Çıktı aşağıdaki şekilde olacaktır:
[1; -2; 4; 5; 8]
Sonraki örnekte kullanımı gösterilmektedir List.sortWith
. Bu örnekte, özel karşılaştırma işlevi compareWidgets
önce özel türdeki bir alanı karşılaştırmak için, sonra ilk alanın değerleri eşit olduğunda başka bir alanı karşılaştırmak için kullanılır.
type Widget = { ID: int; Rev: int }
let compareWidgets widget1 widget2 =
if widget1.ID < widget2.ID then -1 else
if widget1.ID > widget2.ID then 1 else
if widget1.Rev < widget2.Rev then -1 else
if widget1.Rev > widget2.Rev then 1 else
0
let listToCompare = [
{ ID = 92; Rev = 1 }
{ ID = 110; Rev = 1 }
{ ID = 100; Rev = 5 }
{ ID = 100; Rev = 2 }
{ ID = 92; Rev = 1 }
]
let sortedWidgetList = List.sortWith compareWidgets listToCompare
printfn "%A" sortedWidgetList
Çıktı aşağıdaki şekilde olacaktır:
[{ID = 92;
Rev = 1;}; {ID = 92;
Rev = 1;}; {ID = 100;
Rev = 2;}; {ID = 100;
Rev = 5;}; {ID = 110;
Rev = 1;}]
Listelerde Arama İşlemleri
Listeler için çok sayıda arama işlemi desteklenir. En basit olan List.find, belirli bir koşulla eşleşen ilk öğeyi bulmanızı sağlar.
Aşağıdaki kod örneği, bir listede 5'e bölünebilen ilk sayıyı bulmak için öğesinin kullanımını List.find
gösterir.
let isDivisibleBy number elem = elem % number = 0
let result = List.find (isDivisibleBy 5) [ 1 .. 100 ]
printfn "%d " result
Sonuç 5'tir.
Öğelerin önce dönüştürülmesi gerekiyorsa, list.pick öğesini çağırın. Bu, bir seçenek döndüren bir işlev alır ve ilk seçenek değerini ararSome(x)
. öğesini List.pick
döndürmek yerine sonucunu x
döndürür. Eşleşen öğe bulunmazsa, List.pick
oluşturur System.Collections.Generic.KeyNotFoundException
. Aşağıdaki kod, kullanımını List.pick
gösterir.
let valuesList = [ ("a", 1); ("b", 2); ("c", 3) ]
let resultPick = List.pick (fun elem ->
match elem with
| (value, 2) -> Some value
| _ -> None) valuesList
printfn "%A" resultPick
Çıktı aşağıdaki şekilde olacaktır:
"b"
Başka bir arama işlemi grubu olan List.tryFind ve ilgili işlevler bir seçenek değeri döndürür. İşlev, List.tryFind
böyle bir öğe varsa bir koşulu karşılayan listenin ilk öğesini, değilse seçenek değerini None
döndürür. List.tryFindIndex varyasyonu, öğenin kendisi yerine bir tane bulunursa öğenin dizinini döndürür. Bu işlevler aşağıdaki kodda gösterilmiştir.
let list1d = [1; 3; 7; 9; 11; 13; 15; 19; 22; 29; 36]
let isEven x = x % 2 = 0
match List.tryFind isEven list1d with
| Some value -> printfn "The first even value is %d." value
| None -> printfn "There is no even value in the list."
match List.tryFindIndex isEven list1d with
| Some value -> printfn "The first even value is at position %d." value
| None -> printfn "There is no even value in the list."
Çıktı aşağıdaki şekilde olacaktır:
The first even value is 22.
The first even value is at position 8.
Listelerde Aritmetik İşlemler
Toplam ve ortalama gibi yaygın aritmetik işlemler Liste modülünde yerleşik olarak bulunur. List.sum ile çalışmak için liste öğesi türünün işlecini desteklemesi +
ve sıfır değerine sahip olması gerekir. Tüm yerleşik aritmetik türler bu koşulları karşılar. List.average ile çalışmak için, öğe türünün ayrılmaz türleri dışlayan ancak kayan nokta türlerine izin veren kalan bir bölüm olmadan bölmeyi desteklemesi gerekir. List.sumBy ve List.averageBy işlevleri bir işlevi parametre olarak alır ve bu işlevin sonuçları toplam veya ortalama değerlerini hesaplamak için kullanılır.
Aşağıdaki kod, , List.sumBy
ve List.average
kullanımını List.sum
gösterir.
// Compute the sum of the first 10 integers by using List.sum.
let sum1 = List.sum [1 .. 10]
// Compute the sum of the squares of the elements of a list by using List.sumBy.
let sum2 = List.sumBy (fun elem -> elem*elem) [1 .. 10]
// Compute the average of the elements of a list by using List.average.
let avg1 = List.average [0.0; 1.0; 1.0; 2.0]
printfn "%f" avg1
Çıkış 1.000000
olur.
Aşağıdaki kod, kullanımını List.averageBy
gösterir.
let avg2 = List.averageBy (fun elem -> float elem) [1 .. 10]
printfn "%f" avg2
Çıkış 5.5
olur.
Listeler ve Demetler
Tanımlama grubu içeren listeler zip ve unzip işlevleriyle değiştirilebilir. Bu işlevler, tek değerlerden oluşan iki listeyi tek bir demet listesinde birleştirir veya bir demet listesini tek değerlerden oluşan iki liste halinde ayırır. En basit List.zip işlevi, tek öğelerden oluşan iki liste alır ve tek bir tanımlama grubu çiftleri listesi oluşturur. Başka bir sürüm olan List.zip3, tek öğelerin üç listesini alır ve üç öğe içeren tek bir tanımlama grubu listesi oluşturur. Aşağıdaki kod örneğinde kullanımı gösterilmektedir List.zip
.
let list1 = [ 1; 2; 3 ]
let list2 = [ -1; -2; -3 ]
let listZip = List.zip list1 list2
printfn "%A" listZip
Çıktı aşağıdaki şekilde olacaktır:
[(1, -1); (2, -2); (3; -3)]
Aşağıdaki kod örneğinde kullanımı gösterilmektedir List.zip3
.
let list3 = [ 0; 0; 0]
let listZip3 = List.zip3 list1 list2 list3
printfn "%A" listZip3
Çıktı aşağıdaki şekilde olacaktır:
[(1, -1, 0); (2, -2, 0); (3, -3, 0)]
İlgili unzip sürümleri olan List.unzip ve List.unzip3, bir tanımlama grubundaki demetlerin ve dönüş listelerinin listesini alır; burada ilk liste her demette ilk olan tüm öğeleri içerir ve ikinci liste de her demetin ikinci öğesini içerir vb.
Aşağıdaki kod örneğinde List.unzip kullanımı gösterilmektedir.
let lists = List.unzip [(1,2); (3,4)]
printfn "%A" lists
printfn "%A %A" (fst lists) (snd lists)
Çıktı aşağıdaki şekilde olacaktır:
([1; 3], [2; 4])
[1; 3] [2; 4]
Aşağıdaki kod örneği List.unzip3'ün kullanımını gösterir.
let listsUnzip3 = List.unzip3 [(1,2,3); (4,5,6)]
printfn "%A" listsUnzip3
Çıktı aşağıdaki şekilde olacaktır:
([1; 4], [2; 5], [3; 6])
Liste Öğeleri üzerinde Çalışma
F# liste öğelerinde çeşitli işlemleri destekler. En basiti, listenin her öğesinde işlev çağırmanızı sağlayan List.iter'dir. Çeşitlemeler, list.iteriList.iter
olmak üzere iki listenin öğeleri üzerinde işlem gerçekleştirmenizi sağlayan List.iter2,her öğenin dizininin her öğe için çağrılan işleve bağımsız değişken olarak geçirilmesi dışında, ve List.iteri
işlevlerinin List.iter2
bir bileşimi olan List.iteri2'yi içerir. Aşağıdaki kod örneğinde bu işlevler gösterilmektedir.
let list1 = [1; 2; 3]
let list2 = [4; 5; 6]
List.iter (fun x -> printfn "List.iter: element is %d" x) list1
List.iteri(fun i x -> printfn "List.iteri: element %d is %d" i x) list1
List.iter2 (fun x y -> printfn "List.iter2: elements are %d %d" x y) list1 list2
List.iteri2 (fun i x y ->
printfn "List.iteri2: element %d of list1 is %d element %d of list2 is %d"
i x i y)
list1 list2
Çıktı aşağıdaki şekilde olacaktır:
List.iter: element is 1
List.iter: element is 2
List.iter: element is 3
List.iteri: element 0 is 1
List.iteri: element 1 is 2
List.iteri: element 2 is 3
List.iter2: elements are 1 4
List.iter2: elements are 2 5
List.iter2: elements are 3 6
List.iteri2: element 0 of list1 is 1; element 0 of list2 is 4
List.iteri2: element 1 of list1 is 2; element 1 of list2 is 5
List.iteri2: element 2 of list1 is 3; element 2 of list2 is 6
Liste öğelerini dönüştüren bir diğer sık kullanılan işlev list.map işlevidir. Bu işlev, bir listenin her öğesine işlev uygulamanıza ve tüm sonuçları yeni bir listeye yerleştirmenize olanak tanır. List.map2 ve List.map3 , birden çok liste alan çeşitlemelerdir. Öğeye ek olarak işlevin her öğenin dizinine geçirilmesi gerekiyorsa List.mapi ve List.mapi2 de kullanabilirsiniz. ile List.mapi
arasındaki List.mapi2
tek fark, iki listeyle çalışmasıdırList.mapi2
. Aşağıdaki örnekte List.map gösterilmektedir.
let list1 = [1; 2; 3]
let newList = List.map (fun x -> x + 1) list1
printfn "%A" newList
Çıktı aşağıdaki şekilde olacaktır:
[2; 3; 4]
Aşağıdaki örnekte kullanımı gösterilmektedir List.map2
.
let list1 = [1; 2; 3]
let list2 = [4; 5; 6]
let sumList = List.map2 (fun x y -> x + y) list1 list2
printfn "%A" sumList
Çıktı aşağıdaki şekilde olacaktır:
[5; 7; 9]
Aşağıdaki örnekte kullanımı gösterilmektedir List.map3
.
let newList2 = List.map3 (fun x y z -> x + y + z) list1 list2 [2; 3; 4]
printfn "%A" newList2
Çıktı aşağıdaki şekilde olacaktır:
[7; 10; 13]
Aşağıdaki örnekte kullanımı gösterilmektedir List.mapi
.
let newListAddIndex = List.mapi (fun i x -> x + i) list1
printfn "%A" newListAddIndex
Çıktı aşağıdaki şekilde olacaktır:
[1; 3; 5]
Aşağıdaki örnekte kullanımı gösterilmektedir List.mapi2
.
let listAddTimesIndex = List.mapi2 (fun i x y -> (x + y) * i) list1 list2
printfn "%A" listAddTimesIndex
Çıktı aşağıdaki şekilde olacaktır:
[0; 7; 18]
List.collect gibi List.map
olur, ancak her öğe bir liste oluşturur ve tüm bu listeler son bir liste halinde birleştirilir. Aşağıdaki kodda, listenin her öğesi üç sayı oluşturur. Bunların tümü tek bir listede toplanır.
let collectList = List.collect (fun x -> [for i in 1..3 -> x * i]) list1
printfn "%A" collectList
Çıktı aşağıdaki şekilde olacaktır:
[1; 2; 3; 2; 4; 6; 3; 6; 9]
Ayrıca, Boole koşulu alan ve yalnızca belirtilen koşulu karşılayan öğelerden oluşan yeni bir liste oluşturan List.filter'i de kullanabilirsiniz.
let evenOnlyList = List.filter (fun x -> x % 2 = 0) [1; 2; 3; 4; 5; 6]
Sonuçta elde edilen liste şeklindedir [2; 4; 6]
.
Harita ve filtrenin bir bileşimi olan List.select, öğeleri aynı anda dönüştürmenizi ve seçmenizi sağlar. List.choose
bir listenin her öğesine bir seçenek döndüren bir işlev uygular ve işlev seçenek değerini Some
döndürdüğünde öğeler için sonuçların yeni bir listesini döndürür.
Aşağıdaki kod, sözcük listesinden büyük harfle yazılmış sözcükleri seçmek için öğesinin kullanımını List.choose
gösterir.
let listWords = [ "and"; "Rome"; "Bob"; "apple"; "zebra" ]
let isCapitalized (string1:string) = System.Char.IsUpper string1[0]
let results = List.choose (fun elem ->
match elem with
| elem when isCapitalized elem -> Some(elem + "'s")
| _ -> None) listWords
printfn "%A" results
Çıktı aşağıdaki şekilde olacaktır:
["Rome's"; "Bob's"]
Birden Çok Listede Çalışma
Listeler birleştirilebilir. İki listeyi bir liste halinde birleştirmek için List.append komutunu kullanın. İkiden fazla listeyi birleştirmek için List.concat'i kullanın.
let list1to10 = List.append [1; 2; 3] [4; 5; 6; 7; 8; 9; 10]
let listResult = List.concat [ [1; 2; 3]; [4; 5; 6]; [7; 8; 9] ]
List.iter (fun elem -> printf "%d " elem) list1to10
printfn ""
List.iter (fun elem -> printf "%d " elem) listResult
Katlama ve Tarama İşlemleri
Bazı liste işlemleri, tüm liste öğeleri arasında bağımlılıklar içerir. Katlama ve tarama işlemleri, her öğede bir işlev çağırmanız gibi List.iter
List.map
ve işlemleridir, ancak bu işlemler hesaplama aracılığıyla bilgi taşıyan biriktirici adlı ek bir parametre sağlar.
Listede hesaplama yapmak için kullanın List.fold
.
Aşağıdaki kod örneği, çeşitli işlemleri gerçekleştirmek için List.fold kullanımını gösterir.
Listeden geçilir; akümülatör acc
, hesaplama devam ederken geçirilen bir değerdir. İlk bağımsız değişken, biriktiriciyi ve liste öğesini alır ve bu liste öğesi için hesaplamanın ara sonucunu döndürür. İkinci bağımsız değişken, biriktiricinin ilk değeridir.
let sumList list = List.fold (fun acc elem -> acc + elem) 0 list
printfn "Sum of the elements of list %A is %d." [ 1 .. 3 ] (sumList [ 1 .. 3 ])
// The following example computes the average of a list.
let averageList list = (List.fold (fun acc elem -> acc + float elem) 0.0 list / float list.Length)
// The following example computes the standard deviation of a list.
// The standard deviation is computed by taking the square root of the
// sum of the variances, which are the differences between each value
// and the average.
let stdDevList list =
let avg = averageList list
sqrt (List.fold (fun acc elem -> acc + (float elem - avg) ** 2.0 ) 0.0 list / float list.Length)
let testList listTest =
printfn "List %A average: %f stddev: %f" listTest (averageList listTest) (stdDevList listTest)
testList [1; 1; 1]
testList [1; 2; 1]
testList [1; 2; 3]
// List.fold is the same as to List.iter when the accumulator is not used.
let printList list = List.fold (fun acc elem -> printfn "%A" elem) () list
printList [0.0; 1.0; 2.5; 5.1 ]
// The following example uses List.fold to reverse a list.
// The accumulator starts out as the empty list, and the function uses the cons operator
// to add each successive element to the head of the accumulator list, resulting in a
// reversed form of the list.
let reverseList list = List.fold (fun acc elem -> elem::acc) [] list
printfn "%A" (reverseList [1 .. 10])
İşlev adında basamak bulunan bu işlevlerin sürümleri birden fazla listede çalışır. Örneğin, List.fold2 iki listede hesaplamalar gerçekleştirir.
Aşağıdaki örnekte kullanımı gösterilmektedir List.fold2
.
// Use List.fold2 to perform computations over two lists (of equal size) at the same time.
// Example: Sum the greater element at each list position.
let sumGreatest list1 list2 = List.fold2 (fun acc elem1 elem2 ->
acc + max elem1 elem2) 0 list1 list2
let sum = sumGreatest [1; 2; 3] [3; 2; 1]
printfn "The sum of the greater of each pair of elements in the two lists is %d." sum
List.fold
ve List.scan , ek parametrenin son değerini döndüren List.fold
ve ek parametrenin List.scan
ara değerlerinin (son değerle birlikte) listesini döndüren için farklıdır.
Bu işlevlerin her biri, listenin geçiş sırasına ve bağımsız değişkenlerin sırasına göre farklılık gösteren List.foldBack gibi ters bir varyasyon içerir. Ayrıca, List.fold
List.foldBack
eşit uzunlukta iki liste alan List.fold2 ve List.foldBack2 çeşitlemelerine de sahiptir. Her öğede yürütülen işlev, bazı eylemler gerçekleştirmek için her iki liste için de ilgili öğeleri kullanabilir. İki listenin öğe türleri, aşağıdaki örnekte olduğu gibi farklı olabilir. Bir listede banka hesabı için işlem tutarları, diğer liste ise işlem türünü içerir: para yatırma veya çekme.
// Discriminated union type that encodes the transaction type.
type Transaction =
| Deposit
| Withdrawal
let transactionTypes = [Deposit; Deposit; Withdrawal]
let transactionAmounts = [100.00; 1000.00; 95.00 ]
let initialBalance = 200.00
// Use fold2 to perform a calculation on the list to update the account balance.
let endingBalance = List.fold2 (fun acc elem1 elem2 ->
match elem1 with
| Deposit -> acc + elem2
| Withdrawal -> acc - elem2)
initialBalance
transactionTypes
transactionAmounts
printfn "%f" endingBalance
Toplama List.fold
gibi bir hesaplama için ve List.foldBack
sonuç dolaşma sırasına bağlı olmadığından aynı etkiye sahiptir. Aşağıdaki örnekte, List.foldBack
öğeleri listeye eklemek için kullanılır.
let sumListBack list = List.foldBack (fun elem acc -> acc + elem) list 0
printfn "%d" (sumListBack [1; 2; 3])
// For a calculation in which the order of traversal is important, fold and foldBack have different
// results. For example, replacing fold with foldBack in the listReverse function
// produces a function that copies the list, rather than reversing it.
let copyList list = List.foldBack (fun elem acc -> elem::acc) list []
printfn "%A" (copyList [1 .. 10])
Aşağıdaki örnek, banka hesabı örneğine döner. Bu kez yeni bir işlem türü eklenir: faiz hesaplaması. Bitiş bakiyesi artık işlemlerin sırasına bağlıdır.
type Transaction2 =
| Deposit
| Withdrawal
| Interest
let transactionTypes2 = [Deposit; Deposit; Withdrawal; Interest]
let transactionAmounts2 = [100.00; 1000.00; 95.00; 0.05 / 12.0 ]
let initialBalance2 = 200.00
// Because fold2 processes the lists by starting at the head element,
// the interest is calculated last, on the balance of 1205.00.
let endingBalance2 = List.fold2 (fun acc elem1 elem2 ->
match elem1 with
| Deposit -> acc + elem2
| Withdrawal -> acc - elem2
| Interest -> acc * (1.0 + elem2))
initialBalance2
transactionTypes2
transactionAmounts2
printfn "%f" endingBalance2
// Because foldBack2 processes the lists by starting at end of the list,
// the interest is calculated first, on the balance of only 200.00.
let endingBalance3 = List.foldBack2 (fun elem1 elem2 acc ->
match elem1 with
| Deposit -> acc + elem2
| Withdrawal -> acc - elem2
| Interest -> acc * (1.0 + elem2))
transactionTypes2
transactionAmounts2
initialBalance2
printfn "%f" endingBalance3
List.reduce işlevi ve işlevine benzerList.scan
List.fold
, ancak ayrı bir akümülatörün List.reduce
etrafından geçmek yerine yalnızca biri yerine öğe türünün iki bağımsız değişkenini alan bir işlev alır ve bu bağımsız değişkenlerden biri, hesaplamanın ara sonucunu depoladığı anlamına gelir. List.reduce
ilk iki liste öğesi üzerinde çalışarak başlar ve ardından sonraki öğeyle birlikte işlemin sonucunu kullanır. Kendi türüne sahip ayrı bir akümülatör olmadığından, List.reduce
yalnızca biriktirici ve öğe türü aynı türe sahip olduğunda kullanılabilir List.fold
. Aşağıdaki kod, kullanımını List.reduce
gösterir. List.reduce
sağlanan listede öğe yoksa bir özel durum oluşturur.
Aşağıdaki kodda lambda ifadesine yapılan ilk çağrıya 2 ve 4 bağımsız değişkenleri verilir ve 6 döndürür ve sonraki çağrıya 6 ve 10 bağımsız değişkenleri verilir, dolayısıyla sonuç 16 olur.
let sumAList list =
try
List.reduce (fun acc elem -> acc + elem) list
with
| :? System.ArgumentException as exc -> 0
let resultSum = sumAList [2; 4; 10]
printfn "%d " resultSum
Listeler ve Diğer Koleksiyon Türleri Arasında Dönüştürme
Modül hem List
dizilere hem de dizilere dönüştürmeye yönelik işlevler sağlar. Bir diziye veya diziden dönüştürmek için List.toSeq veya List.ofSeq kullanın. Bir diziye veya diziden dönüştürmek için List.toArray veya List.ofArray kullanın.
Ek İşlemler
Listelerde ek işlemler hakkında bilgi için, Liste Modülü kitaplık başvurusu konusuna bakın.