> For the complete documentation index, see [llms.txt](https://kurohasu.gitbook.io/fsharpabout/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kurohasu.gitbook.io/fsharpabout/functions/korekushonnona.md).

# コレクション型の重要な高階関数

{% hint style="info" %}
説明には`List`を使いますが、他のコレクションでも対応していれば使い方は同じです\
(対応しているかの確認は[こちらのリスト](/fsharpabout/basic/collection/functions-1.md)をご確認ください)
{% endhint %}

### map(要素変換)

各要素に関数を適用し、適用結果を新しいコレクションとして返します

```fs
//定義:List.map <適応する関数> <入力側のリスト>

//例: input(-3,-2, ... 3)にf(x)=3x-5を適用させる
let input=[-3..3]
let output=
    input
    |>List.map (fun x -> 3*x-5 ) 
    
printfn "output=%A" output
//出力
//output=[-14; -11; -8; -5; -2; 1; 4]
```

### iter(要素を使った繰り返し)

各要素を関数の引数として処理を実行します\
`map`では任意の戻り値があるのに対し、`iter`では`unit`で固定されています\
(反復のiterationからとったみたいです)

```fs
//構文:List.iter <実行する関数> <引数のリスト>

//例:Language("F#","C#","TypeScript")をiter+printfn()で出力する
let Language=["F#";"C#";"TypeScript"]
 Language |> List.iter (fun str -> (printfn "%sを勉強してます" str) )
//出力
//F#を勉強してます
//C#を勉強してます
//TypeScriptを勉強してます
```

### filter(絞り込み)

引数に対して条件式を実行し、trueを返すものを新しいリストとして返します\
存在しない場合は`KeyNotFoundException`が発生します

```fs
//構文:List.filter <条件式> <引数のリスト>

//例:nums(0,1,2,..20)から偶数のみを抽出
let nums=[0..20]
let even=
    nums
    |> List.filter (fun x ->x%2=0 )
```

### choose(絞り込み&要素変換)

リスト内の要素をあらかじめOption型にして条件に当てはまる要素を抽出します([Option型についてはこちら](/fsharpabout/advance/tapurutoopushon.md#opushon))\
filterでは数式的な条件に限られていましたが、<mark style="color:$info;">**chooseではif/matchを値として使用できます**</mark>

```fs
//構文:List.choose <条件式となる関数> <引数のリスト>

//例:stringの配列inputsを受け取り数字|記号が含まれているものは除外する
open System.Text.RegularExpressions    //正規表現ではじくためのモジュール
let alphaRegex = Regex("^[A-Za-z]+$")    //正規表現
let parseAlpha (s: string) =if alphaRegex.IsMatch(s) then (Some s) else None
// ↑正規表現を満たさない場合はNoneを返す条件式(関数)

let inputs=["OnlyMsg";"AA!!!!!$%$%";"w4nn463p455"]
let filtered=
    inputs
    |> List.choose parseAlpha
     
printfn "inputs filtered %A" filtered
//出力
//inputs filtered ["OnlyMsg"]
```

### fold(畳み込み)

初期値を設定し単一の値になるよう畳み込みを行います

```fs
//構文:List.fold <畳み込みのための関数> <初期値> <引数のリスト>

//例:nums(0,1,2,..10)の総和(初期値initNum)を求める
let initNum=0
let nums=[0..10]
let sums=
    nums
    |> List.fold (fun prev x ->prev+x ) initNum 
    
printfn "SUM=%d" sums
//出力
//SUM=55

//(fun prev x ->prev+x)はprev→それまでの値、x→参照する値となる
//(((initNum+0)+1)+2)...と計算されていく
```

{% hint style="info" %}
リストの要素が空でないことを保証できる場合、最初の要素を初期値として同じことを行える`reduce()`もあります
{% endhint %}

### collect(変換＆平坦化)

要素をリスト化し、1次元リストに変換します(mapping+concat)\
`List<List<int>>` のようなネスト構造になっている場合に有効です

```fs
//構文:List.collect <変換するための関数> <引数のリスト>

//例:stringsをArray.split()し、それをリスト化し、1次元のリストに変換する
let strings=["hello world"; "fsharp is fun"]
let flattenStrings=
    strings
    |>List.collect (fun s ->s.Split(' ')|>Array.toList )
printfn "flattened string:%A" flattenStrings
//出力
//flattened string:["hello"; "world"; "fsharp"; "is"; "fun"]
```

### exists(存在の確認)

要素内に条件を満たすものが<mark style="color:$info;">**1つでもあれば**</mark>true,そうでなければfalseを返します

```fs
//構文:List.exists <条件式> <引数のリスト>

//例:Language2("F#","C#","VB.NET","TypeScript")内に7文字以上の要素があるか判定
let Language2=["F#";"C#";"VB.NET";"TypeScript"]
let checkpredicate=
    Language2
    |>List.exists (fun x -> x.Length>=7 )

if checkpredicate then printfn "7文字以上の言語を発見しました"
//出力
//7文字以上の言語を発見しました
```

### forall(すべての条件を満たすか)

要素が条件を<mark style="color:$info;">**全て満たす場合は**</mark>true,そうでなければfalseを返します

```fs
//構文:List.forall <条件式> <引数のリスト>

//例:Language2("F#","C#","VB.NET","TypeScript")内の要素が全て2文字以上か判定
let Language2=["F#";"C#";"VB.NET";"TypeScript"]
let checkpredicate=
    Language2
    |>List.forall (fun x -> x.Length>=2 )

if checkpredicate then printfn "全ての言語は2文字以上です"
//出力
//全ての言語は2文字以上です
```

### groupBy(グループ化)

要素に対してインデックス算出のための関数を適用し、その場所に要素を格納したリストを返します\
`(keyの値keyに属する要素 のリスト)のタプル のリスト` の形で出力され、keyの出力された順番で並びます

```fs
//構文:List.groupBy <インデックス算出のための関数> <引数のリスト>

//例:(0,1,...20)までの値を8で割った時の余りをキーとしてグループ化
let nums=[0..20]
let grouped=
    nums
    |> List.groupBy (fun x -> x%8 )
    
grouped
|>List.iteri ( fun _ (key,vals) ->    
//インデックスを_で無視,要素を取得(キー値:key,格納されている要素:vals)
    printfn "%dをキーとして%Aが格納されている" key vals
)

//出力
//0をキーとして[0; 8; 16]が格納されている
//1をキーとして[1; 9; 17]が格納されている
//2をキーとして[2; 10; 18]が格納されている
//3をキーとして[3; 11; 19]が格納されている
//4をキーとして[4; 12; 20]が格納されている
//5をキーとして[5; 13]が格納されている
//6をキーとして[6; 14]が格納されている
//7をキーとして[7; 15]が格納されている
```
