قوائم (F#)

A قائمة في F# هو an ordered, immutable series of عناصر of the same نوع.

Creating و Initializing Lists

You can define a قائمة بواسطة بوضوح listing خارج the عناصر, separated بواسطة semicolons و enclosed في square brackets, كـ shown في the following خط of تعليمات برمجية.

let list123 = [ 1; 2; 3 ]

You can also put خط breaks between عناصر, في which حالة the semicolons are اختياري. The latter بناء الجملة can النتيجة في المزيد readable تعليمات برمجية when the عنصر تهيئة expressions are longer, أو when you want إلى تضمين a تعليق for each عنصر.

let list123 = [
    1
    2
    3 ]

Normally, الجميع قائمة عناصر must be the same نوع. An ‏‏ استثناء هو that a قائمة في which the عناصر are specified إلى be a الأساس نوع can have عناصر that are الأنواع المشتقة. Thus the following هو acceptable, because كلاهما Button و CheckBox derive من Control.

let myControlList : Control list = [ new Button(); new CheckBox() ]

You can also define قائمة عناصر بواسطة using a range indicated بواسطة integers separated بواسطة the range عامل (..), كـ shown في the following تعليمات برمجية.

let list1 = [ 1 .. 10 ]

You can also define a قائمة بواسطة using a looping construct, كـ في the following تعليمات برمجية.

let listOfSquares = [ for i in 1 .. 10 -> i*i ]

An فارغ قائمة هو specified بواسطة a ينشئ ازدواجًا of square brackets مع لا شيء في between them.

// An empty list.
let listEmpty = []

يمكنك أيضا استخدام تعبير تسلسل إلى إنشاء قائمة. راجع "تسلسلات التعبيرات" في التسلسل. على سبيل المثال، ما يلي تعليمات برمجية ينشئ قائمة مربعات الأرقام من 1 إلى 10.

let squaresList = [ for i in 1 .. 10 -> i * i ]

عوامل للعمل مع القوائم

يمكنك يرفق عناصر إلى قائمة باستخدام ::عامل التشغيل (اتصالات). إذا list1هو [2; 3; 4]، يقوم بإنشاء تعليمات برمجية التالية list2كـ [100; 2; 3; 4].

let list2 = 100 :: list1

يمكن أن تقوم بعمل سلسلة القوائم التي تحتوي على أنواع متوافقة باستخدام @عامل، كما في ما يلي تعليمات برمجية. Iflist1هو[2; 3; 4]وlist2هو[100; 2; 3; 4 ], this تعليمات برمجية createslist3كـ[2; 3; 4; 100; 2; 3; 4].

let list3 = list1 @ list2

دالات لتنفيذ العمليات تشغيل القوائم متوفر في قائمة وحدة نمطية?.

لأن التغير قوائم ب #، توليد أي العمليات تعديل القوائم الجديدة بدلاً من تعديل قوائم موجودة.

يتم تنفيذ Lهوts في ب # lهوts المرتبطة مفرد، مما يعني أن العمليات الوصول إليه فقط رأس lهوt O(1)، وعنصر الوصول هو O(n).

Properties

قائمة يعتمد نوع الخصائص التالية:

الخصائص

Type

الوصف

head

'T

أول عنصر.

فارغ

bool

trueإذا قائمة على عدم وجود عناصر.

isEmpty

bool

trueإذا قائمة على عدم وجود عناصر.

العنصر

'T

العنصر في المحدد فهرس (zero-based).

الطول

int

عدد العناصر.

Tail

'T list

قائمة دون العنصر أول.

فيما يلي بعض الأمثلة عن استخدام هذه الخصائص.

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))

استخدام القوائم

يمكنك برمجة مع القوائم إلى إجراء العمليات معقدة بمقدار مربع متوسط من تعليمات برمجية. يصف هذا القسم العمليات عام تشغيل القوائم التي لها أهمية بالنسبة إلى البرمجة الوظيفية.

العودية مع القوائم

قوائم مناسبة بشكل فريد إلى العودية تقنيات البرمجة. خذ بعين الاعتبار عملية التي يجب تنفيذها تشغيل كل عنصر قائمة. يمكنك القيام بترتيب هو بالتشغيل تشغيل رأس lهوt وتمرير ذيل lهوt، ثم بشكل متكرر حيث هو lهوt أصغر تلك consهوts من lهوt الأصلي دون العنصر أول، وظهر مرة أخرى إلى المستوى التالي من العودية.

إلى الكتابة مثل عودي دالة، استخدام operaإلىr اتصالات ( ::) في مطابقة نقش، مما يتيح لك إلى منفصلاً رأس قائمة خلفي.

يلي تعليمات برمجية مثال يوضح كيفية استخدام مطابقة نقش لتنفيذ دالة العودية الذي يقوم بإجراء العمليات تشغيل قائمة.

let rec sum list =
    match list with
    | head :: tail -> head + sum tail
    | [] -> 0

السابق تعليمات برمجية يعمل بشكل جيد للقوائم الصغيرة، ولكن لقوائم بقعة صغيرة، فإنه قد تجاوز سعة بنية تخزين العناصر. تحسين تعليمات برمجية التالية هذا الرمز بواسطة استخدام وسيطة تراكمي، تقنية قياسية للعمل باستخدام العودية دالات. استخدم يجعل من تراكمي وسيطة عودي ذيل دالة، والذي يحفظ مسافة مكدس.

let sum list =
    let loop list acc =
        match list with
        | head :: tail -> loop tail (acc + head)
        | [] -> acc
    loop list 0

دالة RemoveAllMultiplesهو عودى دالة التي تأخذ القوائم الثاني. lهوt الأولى تحتوي على الأرقام التي سيتم تمت إزالته له مضاعفات و lهوt الثاني هو lهوt الذي يجب تمت إزالته الأرقام. تستخدم التعليمة البرمجية في المثال التالي هذه دالة عودي إلى التخلص من الجميع غير-الإعداد الأولية من قائمة, وترك قائمة الإعداد الأولية النتيجة.

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 ] [ 2 .. n ]

printfn "Primes Up To %d:\n %A" 100 (GetPrimesUpTo 100)

الإخراج هو كما يلي:

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]

وحدة نمطية? دالات

يوفر وحدة نمطية? قائمة الدالات التي يمكنها الوصول إلى عناصر قائمة. عنصر الرأس هو الطريقة الأسرع والأسهل للوصول. استخدام خاصية رأس أو وحدة نمطية? دالة من قائمة.head. يمكنك الوصول إلى ذيل قائمة بواسطة يتعدى الذيل خاصية List.tail دالة. للبحث عن عنصر حسب الفهرس، استخدم قائمة.nth دالة. List. nth traverses the list. ولذلك، فإنه هو O(n). في حالة استخدام تعليمات برمجية الخاصة بك List. nth frequently, you might want to consider using an array instead of a list. يتم الوصول إلى عنصر في الصفيف O(1).

منطقي العمليات تشغيل Lists

The قائمة.isEmpty دالة determines whether a قائمة has أي عناصر.

The قائمة.موجود دالة applies a منطقي اختبار إلى عناصر of a قائمة و إرجاع true if أي عنصر satisfies the اختبار. قائمة.exists2 هو similar but operates تشغيل successive pairs of عناصر في الثاني lists.

يلي تعليمات برمجية يوضح استخدم List.exists.

// Use List.exists to search for an element of a list that 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)

الإخراج هو كما يلي:

For list [0; 1; 2; 3], contains zero is true

يوضح المثال التالي استخدام 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

الإخراج هو كما يلي:

Lists [1; 2; 3; 4; 5] and [5; 4; 3; 2; 1] have at least one equal element at the same position.

You can استخدم قائمة.forall if you want إلى اختبار whether الجميع the عناصر of a قائمة meet a شرط.

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])

الإخراج هو كما يلي:

true
false

Similarly, قائمة.forall2 determines whether الجميع عناصر في the corresponding positions في الثاني lists satisfy a منطقي تعبير that involves each ينشئ ازدواجًا of عناصر.

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])

الإخراج هو كما يلي:

true
false

فرز العمليات تشغيل Lists

The قائمة.فرز, قائمة.sortBy, و قائمة.sortWith دالات فرز lists. The فرز دالة determines which of these three دالات إلى استخدم. List.sort uses الافتراضي generic المقارنة. Generic المقارنة uses عمومي عوامل تشغيل based تشغيل the generic يقارن دالة إلى يقارن قيم. يعمل بكفاءة مع مجموعة متنوعة من أنواع العناصر، مثل كـ أنواع الرقمية البسيطة والمجموعات عن، السجلات، الاتحادات discriminated، قوائم، صفائف أي نوع تطبيق IComparable. أنواع تطبيق IComparableالعامة المقارنة يستخدم CompareToدالة. عام المقارنة كما يعمل مع السلاسل، ولكن يستخدم بترتيب فرز مستقلة عن الثقافة. مقارنة عامة يجب عدم استخدام تشغيل الأنواع غير معتمدة، مثل دالة أنواع. أيضا، أن أداء المقارنة العام الافتراضي أفضل لبناء مربع متوسط أنواع؛ لبناء بقعة صغيرة أنواع التي تحتاج إلى أن تكون مقارنة وفرزها بشكل متكرر، يجب مراعاة تطبيق IComparableويوفر تطبيق فعال CompareToالأسلوب.

List.sortByتأخذ دالة تقوم بإرجاع القيمة هو استخدامها كمعايير فرز، وList.sortWithتأخذ دالة comparهوon كوسيطة. تفيد هذه الدالات الثاني الأخيرة عند العمل مع أنواع التي لا تعتمد المقارنة، أو عندما يتطلب المقارنة دلالات المقارنة أكثر تعقيداً، كما في حالة من سلاسل على علم بالبيانات الموروثة.

يوضح المثال التالي استخدام List.sort.

let sortedList1 = List.sort [1; 4; 8; -2; 5]
printfn "%A" sortedList1

الإخراج هو كما يلي:

[-2; 1; 4; 5; 8]

يوضح المثال التالي استخدام List.sortBy.

let sortedList2 = List.sortBy (fun elem -> abs elem) [1; 4; 8; -2; 5]
printfn "%A" sortedList2

الإخراج هو كما يلي:

[1; -2; 4; 5; 8]

التالي مثال يوضح استخدم List.sortWith. في ترتيب هو سبيل المثال، الدالة المخصصة comparهوon compareWidgetsهو يستخدم لأول مرة تقوم بمقارنة حقل واحد من نوع مخصص، وعند آخر ثم قيم الحقل أول هي المساواة.

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

الإخراج هو كما يلي:

  [{ID = 92;
    Rev = 1;}; {ID = 92;
                Rev = 1;}; {ID = 100;
                            Rev = 2;}; {ID = 100;
                                        Rev = 5;}; {ID = 110;
                                                    Rev = 1;}]

Operatiتشغيلs تشغيل قوائم بحث

يتم اعتماد العديد من العمليات بحث للقوائم. أبسط، قائمة.بحث، يتيح لك إلى العثور على العنصر أول الذي يطابق شرط معين.

يوضح مثال التعليمة البرمجية التالية استخدم List.findللعثور على رقم أول التي هو divهوible قبل 5 في lهوt.

let isDivisibleBy number elem = elem % number = 0
let result = List.find (isDivisibleBy 5) [ 1 .. 100 ]
printfn "%d " result

النتيجة هو 5.

إذا كان يجب أن يتم تحويل العناصر أولاً، استدعاء قائمة.pick ، الذي يكون دالة إرجاع خياراً، والبحث عن القيمة خيار أول هو Some(x). وبدلاً من إرجاع عنصر، List.pickإرجاع النتيجة x. في حالة عدم وجود عنصر مطابق هو العثور على، List.pickيطرح [T:System.Collections.Generic,KeyNotFoundException]. يلي تعليمات برمجية يظهر استخدم List.pick.

let valuesList = [ ("a", 1); ("b", 2); ("c", 3) ]

let result = List.pick (fun elem -> if (snd elem = 2) then Some(fst elem) else None) valuesList
printfn "%A" result

الإخراج هو كما يلي:

("b", 2)

مجموعة أخرى من العمليات بحث، من قائمة.tryFind و الدالات ذات الصلة، بإرجاع القيمة خيار. List.tryFindدالة بإرجاع العنصر أول من قائمة التي شرطا في حالة وجود أحد عناصر، ولكن القيمة خيار Noneإذا عدم. إرجاع التباين من قائمة.tryFindIndex الفهرس عنصر، إذا تم العثور على واحد، بدلاً عنصر نفسه. هذه دالات هي موضحة في تعليمات برمجية التالية.

let list1 = [1; 3; 7; 9; 11; 13; 15; 19; 22; 29; 36]
let isEven x = x % 2 = 0
match List.tryFind isEven list1 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 list1 with
| Some value -> printfn "The first even value is at position %d." value
| None -> printfn "There is no even value in the list."

الإخراج هو كما يلي:

The first even value is 22.
The first even value is at position 8.

العمليات الحسابية تشغيل القوائم

عام العمليات حسابية مثل كـ جمع والمعدل مضمنة في قائمة وحدة نمطية?. إلى يجب أن يدعم العمل مع قائمة.جمع ، نوع عنصر القائمة +operaإلىr ويحتوي أية القيمة. الجميع أنواع حسابية مضمنة تفي بالشروط التالية. إلى يجب أن يدعم العمل مع قائمة.متوسط ، نوع عنصر القسمة دون الباقي منه، باستثناء الأنواع المتكاملة ولكن يسمح لأنواع الفاصلة العائمة. قائمة.sumBy ودالات قائمة.averageBy تأخذ دالة كمعلمة، وتستخدم نتائج هذه الدالة إلى حساب قيم جمع أو المتوسط.

يلي تعليمات برمجية يوضح استخدم List.sum، List.sumBy، و List.average.

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]
let avg1 = List.average [0.0; 1.0; 1.0; 2.0]
printfn "%f" avg1

المخرج هو 1.000000.

يلي تعليمات برمجية يظهر استخدم List.averageBy.

let avg2 = List.averageBy (fun elem -> float elem) [1 .. 10]
printfn "%f" avg2

المخرج هو 5.5.

يسرد المجموعات و عن

يمكن أن تتم معالجة القوائم التي تحتوي على المجموعات عن بريدي و إلغاء ضغط الدالات. دمج هذه الدالات الثاني قيم مفردة في قائمة المجموعات عن مفرد أو قائمة واحدة منفصلة للمجموعات عن في قوائم الثاني قوائم القيم المفردة. تأخذ أبسط List.zip دالة قائمتين لعناصر مفردة و ينتج عن قائمة واحدة من أزواج المجموعة. الإصدار آخر، List.zip3، يأخذ القوائم ثلاثة عناصر مفردة و ينشيء المجموعات عن من ثلاثة عناصر قائمة مفردة. يلي تعليمات برمجية يوضح المثال استخدم List.zip.

let list1 = [ 1; 2; 3 ]
let list2 = [ -1; -2; -3 ]
let listZip = List.zip list1 list2
printfn "%A" listZip

الإخراج هو كما يلي:

[(1, -1); (2, -2); (3; -3)]

يلي تعليمات برمجية يوضح المثال استخدم List.zip3.

let list3 = [ 0; 0; 0]
let listZip3 = List.zip3 list1 list2 list3
printfn "%A" listZip3

الإخراج هو كما يلي:

[(1, -1, 0); (2, -2, 0); (3, -3, 0)]

المقابل إلغاء ضغط الإصدارات، قائمة.unzip قائمة.unzip3 ، تأخذ المجموعات عن قوائم وإرجاع قوائم في المجموعة، الموقع القائمة الأولى يحتوي تشغيل الجميع العناصر التي كانت الأولى في كل من المجموعة والقائمة ثانية يحتوي تشغيل العنصر الثاني من كل المجموعة، وهكذا.

يلي تعليمات برمجية يوضح المثال استخدم من قائمة.unzip.

let lists = List.unzip [(1,2); (3,4)]
printfn "%A" lists
printfn "%A %A" (fst lists) (snd lists)

الإخراج هو كما يلي:

([1; 3], [2; 4])
[1; 3] [2; 4]

يوضح مثال التعليمة البرمجية التالية استخدم من قائمة.unzip3.

let listsUnzip3 = List.unzip3 [(1,2,3); (4,5,6)]
printfn "%A" listsUnzip3

الإخراج هو كما يلي:

([1; 4], [2; 5], [3; 6])

تعمل تشغيل عناصر قائمة

F# يدعم العديد من العمليات تشغيل عناصر القائمة. هو الأبسط List.iter ، التي تمكنك من استدعاء دالة في كل عنصر قائمة. تضمين اختلافات Lهوt.iter2 ، التي تمكنك من إجراء عملية تشغيل عناصر lهوts اثنين، Lهوt.iteri، الذي هو مثل List.iterإلا أن الفهرس لكل عنصر هو تمرير كوسيطة للدالة التي هو استدعاء لكل عنصر، و Lهوt.iteri2، الذي هو خليط من الأداء الوظيفي ل List.iter2و List.iteri.

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

الإخراج هو كما يلي:

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

الدالة استخداماً آخر يقوم بتحويل عناصر القائمة هو List.مخطط ، مما يتيح لك إلى يطبق دالة إلى كل عنصر في قائمة ووضع الجميع نتائج في إلى قائمة جديدة. قائمة.map2 و من قائمة.map3 هي الاختلافات التي تأخذ قوائم متعددة. يمكنك أيضا استخدم قائمة.mapi و قائمة.mapi2 ، إذا كان العنصر، بالإضافة إلى متطلبات وظيفة تمرير فهرس لكل عنصر. الاختلاف الوحيد بين List.mapi2و List.mapiهو التي List.mapi2معهم lهوts الثاني. يلي مثال يوضح من قائمة.مخطط.

let list1 = [1; 2; 3]
let newList = List.map (fun x -> x + 1) list1
printfn "%A" newList

الإخراج هو كما يلي:

[2; 3; 4]

يلي مثال يظهر استخدم 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

الإخراج هو كما يلي:

[5; 7; 9]

يلي مثال يظهر استخدم List.map3.

let newList2 = List.map3 (fun x y z -> x + y + z) list1 list2 [2; 3; 4]
printfn "%A" newList2

الإخراج هو كما يلي:

[7; 10; 13]

يلي مثال يظهر استخدم List.mapi.

let newListAddIndex = List.mapi (fun i x -> x + i) list1
printfn "%A" newListAddIndex

الإخراج هو كما يلي:

[1; 3; 5]

يلي مثال يظهر استخدم List.mapi2.

let listAddTimesIndex = List.mapi2 (fun i x y -> (x + y) * i) list1 list2
printfn "%A" listAddTimesIndex

الإخراج هو كما يلي:

[0; 7; 18]

Lهوt.collect هو مثل List.map، إلا أنه يعطي كل عنصر lهوt ويتم وضع سلسلة lهوts هذه في lهوt النهائية. في ما يلي تعليمات برمجية، ينشئ كل عنصر في قائمة الأرقام الثلاثة. هذه الجميع التي تم تجميعها في إحدى قائمة.

let collectList = List.collect (fun x -> [for i in 1..3 -> x * i]) list1
printfn "%A" collectList

الإخراج هو كما يلي:

[1; 2; 3; 2; 4; 6; 3; 6; 9]

يمكنك أيضا استخدام List.عامل تصفية ، الذي يكون شرط منطقية و قم بإنشاء قائمة جديدة تتكون من العناصر التي تفي بشرط معين فقط.

let evenOnlyList = List.filter (fun x -> x % 2 = 0) [1; 2; 3; 4; 5; 6]

الناتج عن عملية الدمج قائمة هو [2; 4; 6].

تركيبة من مخطط وعوامل تصفية، من قائمة.اختيار يمكنك إلى تحويل وتحديد عناصر في نفس الوقت. List.chooseتطبيق دالة التي إرجاع الخيارات لكل عنصر قائمة، و إرجاع قائمة نتائج لعناصر جديدة عند الدالة إرجاع القيمة خيارSome.

يلي تعليمات برمجية يوضح استخدام List.chooseلتحديد مكتوبة بكلمات من قائمة الكلمات.

let listWords = [ "and"; "Rome"; "Bob"; "apple"; "zebra" ]
let isCapitalized (string1:string) =
    string1.Chars(0) >= 'A' && string1.Chars(0) <= 'Z'
let results = List.choose (fun elem -> if isCapitalized elem then Some(elem) else None) listWords
printfn "%A" results

الإخراج هو كما يلي:

["Rome"; "Bob"]

تعمل تشغيل قوائم متعددة

قوائم يمكن وصلها مع بعضها البعض. في صلة قائمتين في الاستخدام واحد، من قائمة.append. إلى ضم المزيد القائمتين، استخدم من قائمة.concat.

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] ]

طي و تفحص العمليات

بعض قائمة تتضمن العمليات interdependencies بين كل قائمة العناصر. عمليات طي وفحص تشبه List.iterو List.mapالتي تقوم باستدعاء دالة تشغيل كل عنصر، لكن هذه العمليات بتوفير معلمة إضافى تسمى تراكمي يحمل المعلومات من خلال الحساب.

استخدام List.foldإلى إجراء عملية حسابية تشغيل القائمة.

يوضح مثال التعليمة البرمجية التالية استخدم قائمة.fold لتنفيذ العمليات مختلفة.

هو traversed القائمة؛ تراكمي accالقيمة التي يتم تمريرها إلى جانب يتتابع الحساب. يأخذ وسيطة الأولى تراكمي و عنصر قائمة، و مؤقتة ناتج العمليات الحسابية الخاصة بعنصر القائمة هذا. وسيطة ثانية هي القيمة الابتدائية تراكمي.

// The following example adds the elements of a list.
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])

تعمل إصدارات هذه الوظائف التي تحتوي أرقام في اسم دالة تشغيل المزيد قائمة. تشغيل سبيل المثال، من قائمة.fold2 بتنفيذ حسابات تشغيل قائمتين.

يوضح المثال التالي استخدام 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 and List.scan differ in that List.fold returns the final value of the extra parameter, but List.scan returns the list of the intermediate values (along with the final value) of the extra parameter.

Each of these دالات يتضمن a عكسى variation, for مثال, قائمة.foldBack, which differs في the ترتيب في which the قائمة هو traversed و the ترتيب of the الوسيطات. Also, List.fold و List.foldBack have variations, قائمة.fold2 و قائمة.foldBack2, that take الثاني lists of equal الطول. The دالة that executes تشغيل each عنصر can استخدم corresponding عناصر of كلاهما lists إلى perform some إجراء. The عنصر أنواع of the الثاني lists can be different, كـ في the following مثال, في which واحد قائمة يحتوي على عملية amounts for a bank account, و the غير ذلك قائمة يحتوي على the نوع of عملية: deposit أو withdrawal.

// 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

For a calculation مثل summation, List.fold و List.foldBack have the same effect because the النتيجة does not depend تشغيل the ترتيب of traversal. في the following مثال, List.foldBack هو used إلى إضافة the عناصر في a قائمة.

let sumListBack list = List.foldBack (fun acc elem -> 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])

The following مثال إرجاع إلى the bank account مثال. This الوقت a جديد عملية نوع هو تمت الإضافة: an interest calculation. The الإنهاء موازنة now depends تشغيل the ترتيب of transactions.

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

الدالة من Lهوt.reduce هو إلى حد ما مثل List.foldو List.scan، إلا أنه بدلاً من تمرير حول تراكمي منفصلة، List.reduceتأخذ دالة التي تأخذ الوسيطتين نوع عنصر بدلاً من واحدة فقط، ومن تلك تصرفات الوسيطات تراكمي، وهذا يعني أن تخزنها المتوسطة نتيجة الحساب. List.reduceيبدأ بالتشغيل تشغيل عناصر قائمة الثاني أول، و ثم يستخدم نتيجة العملية بالإضافة إلى العنصر التالي. لأن هناك هو لا منفصل تراكمي يحتوي الخاصة به نوع، List.reduceيمكن استخدامه بدلاً من List.foldفقط عندما يكون في تراكمي ونوع العنصر نفس النوع. يلي تعليمات برمجية يوضح استخدم List.reduce. List.reduceيطرح إستثناء في حالة توفير القائمة تحتوي على عناصر لا.

في التعليمة البرمجية التالية، الاستدعاء أول إلى التعبير لامدا إعطاء الوسيطات 2 و 4، ترجع 6، والمكالمة التالية تعطي الوسيطات 6 و 10، حيث يكون الناتج هو 16.

let sumList list =
    try
        List.reduce (fun acc elem -> acc + elem) list
    with
       | :? System.ArgumentException as exc -> 0

let resultSum = sumList [2; 4; 10]
printfn "%d " resultSum

تحويل بين قوائم و أنواع مجموعة غير ذلك

Listوحدة نمطية? يوفر وظائف للتحويل إلى و من كل من تسلسلات و صفائف. إلى تحويل إلى أو من تسلسل، استخدم قائمة.toSeq أو قائمة.ofSeq . إلى تحويل إلى أو من صفيفة، استخدم قائمة.إلىArray أو قائمة.ofArray .

العمليات إضافى

للحصول تشغيل معلومات العمليات إضافى تشغيل القوائم، راجع الموضوع مرجع مكتبة الوحدة النمطية Collections.List (F #).

راجع أيضًا:

المرجع

تسلسلات (F#)

خيارات (F#)

موارد أخرى

مرجع لغة ب #

أنواع ب #

صفائف (F#)