学習の記録−7

リスト

F#でのリスト、以下のように書く。List.headで頭、List.tailで頭以外の要素を取得できる。

> let lst = 1::2::3::[];;

val lst : int list = [1; 2; 3]

> List.head lst;;
val it : int = 1
> List.tail lst;;
val it : int list = [2; 3]
> let f lst = 
    match lst with 
    | [] -> "Empty"
    | _::_ -> "Exists"
;;

val f : 'a list -> string

> f lst;;
val it : string = "Exists"

パターンマッチで使用している_::_は「コンス パターン」というものらしい。パターンの一覧はF#入門でまとめられているのが便利なので、これを参照するのがいい。

リスト内包表記

こんな書き方もできるらしい。

open System
 
let f x = [for i in 1..10 do yield x * i]
let g x = [for i in 1..10 -> x * i]
 
Console.WriteLine (f 1);;
Console.WriteLine (g 1);;

foldはreduceをパワーアップさせたもの(初期値指定が可能)

こんな感じで「文中にある母音の数を数える」コードも簡単にかける。

open System
 
let countVowels (str : string) = 
  let charList = List.ofSeq str
 
  let addFunc (As, Es, Is, Os, Us) letter = 
    if   letter = 'a' then (As + 1, Es, Is, Os, Us) 
    elif letter = 'e' then (As, Es + 1, Is, Os, Us)
    elif letter = 'i' then (As, Es, Is + 1, Os, Us)
    elif letter = 'o' then (As, Es, Is, Os + 1, Us)
    elif letter = 'u' then (As, Es, Is, Os, Us + 1)
    else (As, Es, Is, Os, Us)
  List.fold addFunc (0, 0, 0, 0, 0) charList;;
 
Console.Write(countVowels "The quick brown fox jumps over the lazy dog");;

リストの結合

List.append関数使うか、@演算子使うか。

> [1..3]@[4..7];;
val it : int list = [1; 2; 3; 4; 5; 6; 7]
> List.append [1..3] [4..7];;
val it : int list = [1; 2; 3; 4; 5; 6; 7]

リストの部分集合抽出(filter, partition)

List.filterは該当部分のみを抽出、List.partition関数はだめだったケースもまとめて返してくれる。

> let x = [1..10];;

val x : int list = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]

> List.filter    (fun n -> abs n > 5) x;;
val it : int list = [6; 7; 8; 9; 10]
> List.partition (fun n -> abs n > 5) x;;
val it : int list * int list = ([6; 7; 8; 9; 10], [1; 2; 3; 4; 5])