リストLists

F# のリストは、順序が指定されており変更できない一連の同じ型の要素です。A list in F# is an ordered, immutable series of elements of the same type. リストに対して基本的な操作を実行するには、 List モジュールの関数を使用します。To perform basic operations on lists, use the functions in the List module.

リストの作成と初期化Creating and Initializing Lists

リストを定義するには、次のコード行に示すように、セミコロンで区切って明示的にリストした要素を角かっこで囲みます。You can define a list by explicitly listing out the elements, separated by semicolons and enclosed in square brackets, as shown in the following line of code.

let list123 = [ 1; 2; 3 ]

要素間に改行を挿入することもできます。その場合はセミコロンの区切り記号を省略できます。You can also put line breaks between elements, in which case the semicolons are optional. 要素の初期化式が長い場合、各要素にコメントを含める場合は、改行の構文を使用するとコードが読みやすくなります。The latter syntax can result in more readable code when the element initialization expressions are longer, or when you want to include a comment for each element.

let list123 = [
    1
    2
    3 ]

通常、リストの要素はすべて同じ型である必要があります。Normally, all list elements must be the same type. 例外として、要素が基本型として指定されているリストには、派生型の要素を含めることができます。An exception is that a list in which the elements are specified to be a base type can have elements that are derived types. したがって次に示す例は、ButtonCheckBox の両方が Control から派生しているため、受け入れられます。Thus the following is acceptable, because both Button and CheckBox derive from Control.

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

また、次のコードで示すように、整数を範囲演算子 (..) で区切って示した範囲を使用して、リストの要素を定義することもできます。You can also define list elements by using a range indicated by integers separated by the range operator (..), as shown in the following code.

let list1 = [ 1 .. 10 ]

空のリストは、間に何も含まない 1 組の角かっこで示します。An empty list is specified by a pair of square brackets with nothing in between them.

// An empty list.
let listEmpty = []

シーケンス式を使用してリストを作成することもできます。You can also use a sequence expression to create a list. 詳細については、「 シーケンス式 」を参照してください。See Sequence Expressions for more information. たとえば、次のコードでは 1 から 10 までの整数の 2 乗のリストが作成されます。For example, the following code creates a list of squares of integers from 1 to 10.

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

リストの操作に使用する演算子Operators for Working with Lists

リストに要素を付加するには、:: (cons) 演算子を使用します。You can attach elements to a list by using the :: (cons) operator. list1[2; 3; 4] の場合、次のコードでは list2[100; 2; 3; 4] として作成されます。If list1 is [2; 3; 4], the following code creates list2 as [100; 2; 3; 4].

let list2 = 100 :: list1

互換性のある型を含むリストを連結するには、次のコードに示すように @ 演算子を使用します。You can concatenate lists that have compatible types by using the @ operator, as in the following code. list1[2; 3; 4] であり、list2[100; 2; 3; 4] の場合、このコードでは list3[2; 3; 4; 100; 2; 3; 4] として作成されます。If list1 is [2; 3; 4] and list2 is [100; 2; 3; 4], this code creates list3 as [2; 3; 4; 100; 2; 3; 4].

let list3 = list1 @ list2

リストに対する操作を実行する関数は、 List モジュールで使用できます。Functions for performing operations on lists are available in the List module.

F# のリストは変更できないため、変更操作を行うと、既存のリストが変更されるのではなく、新しいリストが生成されます。Because lists in F# are immutable, any modifying operations generate new lists instead of modifying existing lists.

F # のリストは、シングルリンクリストとして実装されます。これは、リストの先頭にのみアクセスする操作が O (1) であり、要素アクセスが O (n) であることを意味します。Lists in F# are implemented as singly linked lists, which means that operations that access only the head of the list are O(1), and element access is O(n).

PropertiesProperties

リスト型では次のプロパティがサポートされています。The list type supports the following properties:

プロパティProperty TypeType 説明Description
HeadHead 'T 1 番目の要素。The first element.
Empty 'T list 該当する型の空のリストを返す静的プロパティ。A static property that returns an empty list of the appropriate type.
IsEmptyIsEmpty bool リストに要素がない場合は true です。true if the list has no elements.
ItemItem 'T 指定したインデックスの要素 (起点を 0 とする)。The element at the specified index (zero-based).
[データ型]Length int 要素の数。The number of elements.
TailTail 'T list 1 番目の要素を除いたリスト。The list without the first element.

これらのプロパティを使用したいくつかの例を次に示します。Following are some examples of using these properties.

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

リストの使用Using Lists

リストを使用してプログラミングを行うと、少量のコードで複雑な操作を実行できます。Programming with lists enables you to perform complex operations with a small amount of code. このセクションでは、関数型プログラミングにおいて重要なリストに対する一般的な操作について説明します。This section describes common operations on lists that are important to functional programming.

リストを使用した再帰Recursion with Lists

リストは、再帰的なプログラミング技法に非常に適しています。Lists are uniquely suited to recursive programming techniques. リストのすべての要素に対して実行する必要がある操作があるとします。Consider an operation that must be performed on every element of a list. この操作を再帰的に実行するには、リストの先頭に対して処理を行った後にリストの後部 (元のリストの最初の要素を除いた要素で構成される、元のリストより小さいリスト) を次の再帰レベルに戻します。You can do this recursively by operating on the head of the list and then passing the tail of the list, which is a smaller list that consists of the original list without the first element, back again to the next level of recursion.

このような再帰関数を記述するには、パターン マッチで cons 演算子 (::) を使用します。これによって、リストの先頭を末尾から分離できます。To write such a recursive function, you use the cons operator (::) in pattern matching, which enables you to separate the head of a list from the tail.

パターン マッチを使用して、リストに対する操作を実行する再帰関数を実装する方法を次のコード例に示します。The following code example shows how to use pattern matching to implement a recursive function that performs operations on a list.

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

このコードは小さいリストでは問題なく動作しますが、リストが大きくなると、スタックがオーバーフローする可能性があります。The previous code works well for small lists, but for larger lists, it could overflow the stack. 次に示すコードは、再帰関数の処理では標準的な技法であるアキュムレータ引数を使用して、このコードを改善したものです。The following code improves on this code by using an accumulator argument, a standard technique for working with recursive functions. アキュムレータ引数を使用すると、関数の後部が再帰的になり、スタック領域を節約できます。The use of the accumulator argument makes the function tail recursive, which saves stack space.

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

関数 RemoveAllMultiples は、2 つのリストを受け取る再帰関数です。The function RemoveAllMultiples is a recursive function that takes two lists. 1 番目のリストは、倍数を削除する数値が格納されたリストで、2 番目のリストは、数値を削除する元のリストです。The first list contains the numbers whose multiples will be removed, and the second list is the list from which to remove the numbers. 次の例のコードでは、この再帰関数を使用してリストから素数以外をすべて削除します。その結果、素数のリストが残ります。The code in the following example uses this recursive function to eliminate all the non-prime numbers from a list, leaving a list of prime numbers as the result.

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)

出力は次のようになります。The output is as follows:

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]

モジュール関数Module Functions

List モジュールには、リストの要素にアクセスする関数が用意されています。The List module provides functions that access the elements of a list. 先頭の要素には、最も迅速かつ簡単にアクセスできます。The head element is the fastest and easiest to access. プロパティ head またはモジュール関数リストを使用します 。 head.Use the property Head or the module function List.head. Tail プロパティまたtail 関数を使用して、リストの末尾にアクセスできます。You can access the tail of a list by using the Tail property or the List.tail function. インデックスによって要素を検索するには、 List. n 関数を使用します。To find an element by index, use the List.nth function. List.nth はリストを走査します。List.nth traverses the list. そのため、O (n) です。Therefore, it is O(n). コードで List.nth を頻繁に使用する場合は、リストの代わりに配列を使用すると、効果的である可能性があります。If your code uses List.nth frequently, you might want to consider using an array instead of a list. 配列での要素のアクセスは O(1) です。Element access in arrays is O(1).

リストに対するブール演算Boolean Operations on Lists

IsEmpty関数は、リストに要素があるかどうかを判断します。The List.isEmpty function determines whether a list has any elements.

List. exists関数は、ブール値のテストをリストの要素に適用し、 true いずれかの要素がテストに適合する場合はを返します。The List.exists function applies a Boolean test to elements of a list and returns true if any element satisfies the test. List.exists2 は似ていますが、2つのリストの要素の連続するペアで動作します。List.exists2 is similar but operates on successive pairs of elements in two lists.

List.exists を使用したコードの例を次に示します。The following code demonstrates the use of List.exists.

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

出力は次のようになります。The output is as follows:

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

次の例は、List.exists2 の使い方を示しています。The following example demonstrates the use of 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

出力は次のようになります。The output is as follows:

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

リストのすべての要素が条件を満たしているかどうかをテストする場合は、forall を使用できますYou can use List.forall if you want to test whether all the elements of a list meet a condition.

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

出力は次のようになります。The output is as follows:

true
false

同様に、 array.forall2 は、2つのリスト内の対応する位置にあるすべての要素が、要素の各ペアに関係するブール式を満たすかどうかを判断します。Similarly, List.forall2 determines whether all elements in the corresponding positions in two lists satisfy a Boolean expression that involves each pair of elements.

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

出力は次のようになります。The output is as follows:

true
false

リストに対する並べ替え操作Sort Operations on Lists

リスト並べ替えsortBy、および関数を使用した sortwithリスト。The List.sort, List.sortBy, and List.sortWith functions sort lists. 並べ替え関数は、これら 3 つの関数のどれを使用するかを判断します。The sorting function determines which of these three functions to use. List.sort は、既定の一般的な比較を使用します。List.sort uses default generic comparison. 一般的な比較は、汎用の比較関数に基づくグローバル演算子を使用して、値を比較します。Generic comparison uses global operators based on the generic compare function to compare values. この比較は、単純な数値型、タプル、レコード、判別共用体、リスト、配列、および System.IComparable を実装する任意の型など、広範な要素型で効率的に動作します。It works efficiently with a wide variety of element types, such as simple numeric types, tuples, records, discriminated unions, lists, arrays, and any type that implements System.IComparable. System.IComparable を実装する型の場合は、汎用的な比較で System.IComparable.CompareTo() 関数が使用されます。For types that implement System.IComparable, generic comparison uses the System.IComparable.CompareTo() function. また、汎用的な比較は文字列にも使用できますが、カルチャに依存しない並べ替え順序が使用されます。Generic comparison also works with strings, but uses a culture-independent sorting order. 関数型のようなサポートされない型には、汎用的な比較を使用できません。Generic comparison should not be used on unsupported types, such as function types. また、既定の汎用的な比較は、小さい構造の型の場合に最高のパフォーマンスを示します。比較と並べ替えが頻繁に必要な大きい構造の型の場合は、System.IComparable を実装し、System.IComparable.CompareTo() メソッドを効率的に実装することを考慮してください。Also, the performance of the default generic comparison is best for small structured types; for larger structured types that need to be compared and sorted frequently, consider implementing System.IComparable and providing an efficient implementation of the System.IComparable.CompareTo() method.

List.sortBy 関数は、並べ替え基準として使用される値を返す関数を受け取り、List.sortWith 関数は、比較関数を引数として受け取ります。List.sortBy takes a function that returns a value that is used as the sort criterion, and List.sortWith takes a comparison function as an argument. これら 2 つの関数は、比較をサポートしない型を使用するとき、またはカルチャを認識する文字列の場合のように複雑な比較セマンティクスを必要とする比較の場合に役立ちます。These latter two functions are useful when you are working with types that do not support comparison, or when the comparison requires more complex comparison semantics, as in the case of culture-aware strings.

次の例は、List.sort の使い方を示しています。The following example demonstrates the use of List.sort.

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

出力は次のようになります。The output is as follows:

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

次の例は、List.sortBy の使い方を示しています。The following example demonstrates the use of List.sortBy.

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

出力は次のようになります。The output is as follows:

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

次の例は、List.sortWith の使い方を示しています。The next example demonstrates the use of List.sortWith. この例では、カスタムの比較関数 compareWidgets を使用して、まず、カスタム型の 1 つのフィールドを比較し、最初のフィールドの値が同じである場合は、さらに別のフィールドを比較しています。In this example, the custom comparison function compareWidgets is used to first compare one field of a custom type, and then another when the values of the first field are equal.

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

出力は次のようになります。The output is as follows:

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

リストに対する検索操作Search Operations on Lists

リストに対するさまざまな検索操作がサポートされています。Numerous search operations are supported for lists. 最も単純な リストです。 findを使用すると、特定の条件に一致する最初の要素を検索できます。The simplest, List.find, enables you to find the first element that matches a given condition.

次のコード例では、List.find を使用して、5 で割り切れる最初の数をリストから検索する方法を示します。The following code example demonstrates the use of List.find to find the first number that is divisible by 5 in a list.

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

The result is 5.The result is 5.

最初に要素を変換する必要がある場合は、 List. pickを呼び出します。この関数は、オプションを返す関数を受け取り、である最初のオプション値を検索し Some(x) ます。If the elements must be transformed first, call List.pick, which takes a function that returns an option, and looks for the first option value that is Some(x). List.pick は要素を返す代わりに、結果 x を返します。Instead of returning the element, List.pick returns the result x. 一致する要素が見つからない場合、List.pickSystem.Collections.Generic.KeyNotFoundException をスローします。If no matching element is found, List.pick throws System.Collections.Generic.KeyNotFoundException. List.pick の使用方法を次のコードに示します。The following code shows the use of List.pick.

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

出力は次のようになります。The output is as follows:

"b"

別の検索操作のグループである tryFind と関連する関数は、オプション値を返します。Another group of search operations, List.tryFind and related functions, return an option value. List.tryFind 関数は、条件を満たす要素がリストにある場合は、その最初の要素を返します。条件を満たす要素がない場合は、オプション値 None を返します。The List.tryFind function returns the first element of a list that satisfies a condition if such an element exists, but the option value None if not. バリエーション リスト. tryFindIndex は、要素自体ではなく、要素が見つかった場合はそのインデックスを返します。The variation List.tryFindIndex returns the index of the element, if one is found, rather than the element itself. これらの関数を次のコードに示します。These functions are illustrated in the following code.

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."

出力は次のようになります。The output is as follows:

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

リストに対する算術演算Arithmetic Operations on Lists

Sum や average などの一般的な算術演算は、 List モジュールに組み込まれています。Common arithmetic operations such as sum and average are built into the List module. List. sumを使用するには、リスト要素の型が演算子をサポートし、値が0である必要があり + ます。To work with List.sum, the list element type must support the + operator and have a zero value. すべての組み込み数値型はこの条件を満たしています。All built-in arithmetic types satisfy these conditions. List. averageを使用するには、要素型が剰余のない除算をサポートしている必要があります。これには整数型は含まれませんが、浮動小数点型は許可されます。To work with List.average, the element type must support division without a remainder, which excludes integral types but allows for floating point types. AverageBy関数およびリスト関数は、パラメーターとして関数を受け取ります。この関数の結果は、合計または平均の値を計算するために使用されます。The List.sumBy and List.averageBy functions take a function as a parameter, and this function's results are used to calculate the values for the sum or average.

次のコードは、List.sumList.sumBy、および List.average の使用方法を示しています。The following code demonstrates the use of List.sum, List.sumBy, and List.average.

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

出力は 1.000000 になります。The output is 1.000000.

List.averageBy の使用方法を次のコードに示します。The following code shows the use of List.averageBy.

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

出力は 5.5 になります。The output is 5.5.

リストとタプルLists and Tuples

タプルを含むリストは、zip 関数および unzip 関数で操作できます。Lists that contain tuples can be manipulated by zip and unzip functions. これらの関数は、単一値の 2 つのリストを結合してタプルのリストを 1 つ生成したり、タプルの 1 つのリストを分割して単一の値のリストを 2 つ生成したりします。These functions combine two lists of single values into one list of tuples or separate one list of tuples into two lists of single values. 最も単純な List.zip 関数は、1つの要素の2つのリストを受け取り、組のペアのリストを1つ生成します。The simplest List.zip function takes two lists of single elements and produces a single list of tuple pairs. 別のバージョン ( List.zip3) は、1つの要素の3つのリストを受け取り、3つの要素を持つ組のリストを1つ生成します。Another version, List.zip3, takes three lists of single elements and produces a single list of tuples that have three elements. 次のコード例は、List.zip の使用方法を示します。The following code example demonstrates the use of List.zip.

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

出力は次のようになります。The output is as follows:

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

次のコード例は、List.zip3 の使用方法を示します。The following code example demonstrates the use of List.zip3.

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

出力は次のようになります。The output is as follows:

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

対応する unzip のバージョン、array.unzip3、およびリストは、組内の組と戻り値のリストを取得します。最初のリストには各組の最初の要素が含まれ、2番目のリストには各組の2番目の要素が含まれます。The corresponding unzip versions, List.unzip and List.unzip3, take lists of tuples and return lists in a tuple, where the first list contains all the elements that were first in each tuple, and the second list contains the second element of each tuple, and so on.

次のコード例は、 unzipの使用方法を示しています。The following code example demonstrates the use of List.unzip.

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

出力は次のようになります。The output is as follows:

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

次のコード例は、 array.unzip3の使用方法を示しています。The following code example demonstrates the use of List.unzip3.

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

出力は次のようになります。The output is as follows:

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

リスト要素に対する操作Operating on List Elements

F# は、リストの要素に対するさまざまな操作をサポートしています。F# supports a variety of operations on list elements. 最も単純なのは iterです。これを使用すると、リストのすべての要素に対して関数を呼び出すことができます。The simplest is List.iter, which enables you to call a function on every element of a list. バリエーションには array.iter2が含まれてい ます。これにより、 List.iter 各要素のインデックスは、各要素に対して呼び出される関数に引数として渡され、 array.iteri2はとの機能を組み合わせたものであることを除いて、2つのリストの要素に対して操作を実行でき List.iter2 List.iteri ます。Variations include List.iter2, which enables you to perform an operation on elements of two lists, List.iteri, which is like List.iter except that the index of each element is passed as an argument to the function that is called for each element, and List.iteri2, which is a combination of the functionality of List.iter2 and List.iteri. 次のコード例にこれらの関数を示します。The following code example illustrates these functions.

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

出力は次のようになります。The output is as follows:

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

リスト要素を変換する、よく使用されるもう1つの関数は、list . map です。これにより、リストの各要素に関数を適用し、すべての結果を新しいリストに入れることができます。Another frequently used function that transforms list elements is List.map, which enables you to apply a function to each element of a list and put all the results into a new list. List.map2list.map3 は、複数のリストを受け取るバリエーションです。List.map2 and List.map3 are variations that take multiple lists. また、 array.mapi2 とリストを使用することもできます。この場合、要素に加えて、関数は各要素のインデックスを渡す必要があります。You can also use List.mapi and List.mapi2, if, in addition to the element, the function needs to be passed the index of each element. List.mapi2List.mapi の唯一の違いは、List.mapi2 では 2 つのリストが使用される点です。The only difference between List.mapi2 and List.mapi is that List.mapi2 works with two lists. 次の例は、 List. mapを示しています。The following example illustrates List.map.

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

出力は次のようになります。The output is as follows:

[2; 3; 4]

次の例は、List.map2 の使用方法を示しています。The following example shows the use of 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

出力は次のようになります。The output is as follows:

[5; 7; 9]

次の例は、List.map3 の使用方法を示しています。The following example shows the use of List.map3.

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

出力は次のようになります。The output is as follows:

[7; 10; 13]

次の例は、List.mapi の使用方法を示しています。The following example shows the use of List.mapi.

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

出力は次のようになります。The output is as follows:

[1; 3; 5]

次の例は、List.mapi2 の使用方法を示しています。The following example shows the use of List.mapi2.

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

出力は次のようになります。The output is as follows:

[0; 7; 18]

List. collect はと似ていますが List.map 、各要素によってリストが生成され、これらのすべてのリストが最終的な一覧に連結される点が異なります。List.collect is like List.map, except that each element produces a list and all these lists are concatenated into a final list. 次のコードでは、リストの各要素が 3 つの値を生成します。In the following code, each element of the list generates three numbers. これらすべてが 1 つのリストに集約されます。These are all collected into one list.

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

出力は次のようになります。The output is as follows:

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

また、 list. filterを使用することもできます。これはブール条件を受け取り、指定された条件を満たす要素だけで構成される新しいリストを生成します。You can also use List.filter, which takes a Boolean condition and produces a new list that consists only of elements that satisfy the given condition.

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

結果のリストは [2; 4; 6] です。The resulting list is [2; 4; 6].

[マップ] と [フィルター] の組み合わせで、 [選択] を使用すると、複数の要素を同時に変換および選択できます。A combination of map and filter, List.choose enables you to transform and select elements at the same time. List.choose は、オプションを返す関数をリストの各要素に適用し、関数がオプション値 Some を返す要素の結果から成る新しいリストを返します。List.choose applies a function that returns an option to each element of a list, and returns a new list of the results for elements when the function returns the option value Some.

次のコードでは、List.choose を使用して、最初の文字が大文字の単語を単語のリストから選択しています。The following code demonstrates the use of List.choose to select capitalized words out of a list of words.

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

出力は次のようになります。The output is as follows:

["Rome's"; "Bob's"]

複数のリストに対する操作Operating on Multiple Lists

複数のリストを結合できます。Lists can be joined together. 2つのリストを1つに結合するには、 List. appendを使用します。To join two lists into one, use List.append. 3つ以上のリストを結合するには、 concatを使用します。To join more than two lists, use List.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] ]
List.iter (fun elem -> printf "%d " elem) list1to10
printfn ""
List.iter (fun elem -> printf "%d " elem) listResult

フォールド操作とスキャン操作Fold and Scan Operations

リストの操作の中には、リストのすべての要素間の依存関係を伴うものがあります。Some list operations involve interdependencies between all of the list elements. フォールド操作とスキャン操作は List.iterList.map 各要素に対して関数を呼び出すのと似ていますが、これらの操作には、計算を通じて情報を伝達する アキュムレータ と呼ばれる追加のパラメーターが用意されています。The fold and scan operations are like List.iter and List.map in that you invoke a function on each element, but these operations provide an additional parameter called the accumulator that carries information through the computation.

リストに対して計算を実行するには、List.fold を使用します。Use List.fold to perform a calculation on a list.

次のコード例では、 リスト を使用してさまざまな操作を実行する方法を示します。The following code example demonstrates the use of List.fold to perform various operations.

リストが走査されます。アキュムレータ accは、計算の進行に伴って渡される値です。The list is traversed; the accumulator acc is a value that is passed along as the calculation proceeds. 1 番目の引数はアキュムレータとリスト要素を受け取り、そのリスト要素に対する計算の中間結果を返します。The first argument takes the accumulator and the list element, and returns the interim result of the calculation for that list element. 2 番目の引数はアキュムレータの初期値です。The second argument is the initial value of the accumulator.

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

関数名に数字が付いている関数は、複数のリストを操作するバージョンです。The versions of these functions that have a digit in the function name operate on more than one list. たとえば、 list.fold2 は2つのリストに対して計算を実行します。For example, List.fold2 performs computations on two lists.

次の例は、List.fold2 の使い方を示しています。The following example demonstrates the use of 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 および List. scan は、 List.fold 余分なパラメーターの最後の値を返すのと異なりますが、 List.scan 余分なパラメーターの中間値 (最終的な値と共に) のリストを返します。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.

これらの各関数には、 array.foldbackなどの逆のバリエーションが含まれています。これは、リストが走査される順序と引数の順序によって異なります。Each of these functions includes a reverse variation, for example, List.foldBack, which differs in the order in which the list is traversed and the order of the arguments. また、 List.fold とに List.foldBack は、 list.fold2array.foldback2というバリエーションがあります。これは、同じ長さの2つのリストを受け取ります。Also, List.fold and List.foldBack have variations, List.fold2 and List.foldBack2, that take two lists of equal length. 各要素に対して実行される関数では、両方のリストの対応する要素を使用して操作を実行できます。The function that executes on each element can use corresponding elements of both lists to perform some action. 2 つのリストの要素の型が同じである必要はありません。たとえば、次の例では、一方のリストには銀行口座の取引金額が格納され、もう一方のリストには取引の種類 (預け入れまたは引き出し) が格納されています。The element types of the two lists can be different, as in the following example, in which one list contains transaction amounts for a bank account, and the other list contains the type of transaction: deposit or 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

合計のような計算の場合は、結果が走査の順序に依存しないため、List.foldList.foldBack のどちらを使用しても、同じ結果になります。For a calculation like summation, List.fold and List.foldBack have the same effect because the result does not depend on the order of traversal. 次の例では、List.foldBack を使用してリストの要素を追加します。In the following example, List.foldBack is used to add the elements in a list.

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 example returns to the bank account example. 今度は、利息を計算する新しい取引の種類が追加されています。This time a new transaction type is added: an interest calculation. 取引の順序によって期末残高が異なります。The ending balance now depends on the order 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

関数の 一覧の縮小 は、およびと似ていますが、 List.fold 別の List.scan アキュムレータを渡すのではなく、 List.reduce 1 つだけではなく要素型の2つの引数を受け取る関数を受け取ります。これらの引数の1つはアキュムレータとして機能します。つまり、計算の中間結果が格納されます。The function List.reduce is somewhat like List.fold and List.scan, except that instead of passing around a separate accumulator, List.reduce takes a function that takes two arguments of the element type instead of just one, and one of those arguments acts as the accumulator, meaning that it stores the intermediate result of the computation. List.reduce は、初めに最初の 2 つのリスト要素に対して演算を実行し、次にその演算の結果と次の要素を合わせて使用します。List.reduce starts by operating on the first two list elements, and then uses the result of the operation along with the next element. 独自の型を持つ別のアキュムレータがないため、List.reduceList.fold の代わりに使用できるのは、アキュムレータと要素が同じ型を持つ場合だけです。Because there is not a separate accumulator that has its own type, List.reduce can be used in place of List.fold only when the accumulator and the element type have the same type. List.reduce を使用したコードの例を次に示します。The following code demonstrates the use of List.reduce. 指定されたリストに要素がない場合、List.reduce は例外をスローします。List.reduce throws an exception if the list provided has no elements.

次のコードでは、ラムダ式の最初の呼び出しで引数 2 と 4 を受け取って 6 を返し、次の呼び出しで引数 6 と 10 を受け取るので、結果が 16 になります。In the following code, the first call to the lambda expression is given the arguments 2 and 4, and returns 6, and the next call is given the arguments 6 and 10, so the result is 16.

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

リストと他のコレクション型との変換Converting Between Lists and Other Collection Types

List モジュールには、シーケンスと配列との間で両方向の変換を行うための関数が用意されています。The List module provides functions for converting to and from both sequences and arrays. シーケンスとの間で変換を行うには、 list. toseq または List. ofseqを使用します。To convert to or from a sequence, use List.toSeq or List.ofSeq. 配列との間で変換を行うには、 list. toArray または List. ofarrayを使用します。To convert to or from an array, use List.toArray or List.ofArray.

その他の操作Additional Operations

リストに対するその他の操作の詳細については、ライブラリリファレンストピック リストモジュールを参照してください。For information about additional operations on lists, see the library reference topic List Module.

関連項目See also