Skip to content

F# List入門問題精講

この文書は、F#のリストの様々な関数を使いこなすための練習問題集のPart 1 (基礎編) である。15問を通して、F#のリスト操作の基本をマスターすることを目指す。

問題1: 空リストを作成する

出力:

  • 空のリスト
解答例と解説
let emptyList = []
printfn "%A" emptyList

解説:

[] は空のリストを表す。

問題2: リストの先頭に要素を追加する

入力:

  • 既存のリスト: [2; 3; 4]
  • 追加する要素: 1

出力:

  • [1; 2; 3; 4]
ヒント
  • :: 演算子 (コンス演算子) を使用する
解答例と解説
let existingList = [2; 3; 4]
let elementToAdd = 1
let newList = elementToAdd :: existingList
printfn "%A" newList

解説:

:: 演算子 (コンス演算子) は、リストの先頭に要素を追加する。elementToAdd :: existingList は、existingList の先頭に elementToAdd を追加した新しいリストを作成する。

問題3: 2つのリストを結合する

入力:

  • [1; 2; 3]
  • [4; 5; 6]

出力:

  • [1; 2; 3; 4; 5; 6]
ヒント
  • @ 演算子、または List.append 関数を使用する
解答例と解説
let list1 = [1; 2; 3]
let list2 = [4; 5; 6]
// @ 演算子を使用
let combinedList1 = list1 @ list2
// List.append 関数を使用
let combinedList2 = List.append list1 list2
printfn "%A" combinedList1
printfn "%A" combinedList2

解説:

@ 演算子と List.append 関数はどちらも、2つのリストを結合して新しいリストを作成する。list1 @ list2List.append list1 list2 はどちらも [1; 2; 3; 4; 5; 6] を返す。

問題4: リストの先頭要素を取得する

入力:

  • [1; 2; 3; 4; 5]

出力:

  • 1
ヒント
  • List.head 関数を使用する
  • List.tryHead 関数も類似の機能を提供する (Option 型で結果を返す)
解答例と解説
let list = [1; 2; 3; 4; 5]
let headElement = List.head list
printfn "%d" headElement

解説:

List.head 関数はリストの先頭の要素を返す。この例では、list の先頭要素は 1 なので、headElement1 になる。 注意: 空リストに List.head を適用すると例外が発生する。List.tryHead を使うと、Option 型で結果が返され、空リストの場合は None になるため、例外を回避できる。

問題5: リストの先頭を除いた残りのリストを取得する

入力:

  • [1; 2; 3; 4; 5]

出力:

  • [2; 3; 4; 5]
ヒント
  • List.tail 関数を使用する
解答例と解説
let list = [1; 2; 3; 4; 5]
let tailList = List.tail list
printfn "%A" tailList

解説:

List.tail 関数はリストの先頭を除いた残りのリストを返す。この例では、list の先頭要素 1 を除いた [2; 3; 4; 5]tailList になる。 注意: 空リストに List.tail を適用すると例外が発生する。

問題6: リストが空かどうかを判定する

入力:

  • []
  • [1; 2; 3]

出力:

  • true
  • false
ヒント
  • List.isEmpty 関数を使用する
解答例と解説
let list1 = []
let list2 = [1; 2; 3]
let isEmpty1 = List.isEmpty list1
let isEmpty2 = List.isEmpty list2
printfn "%b" isEmpty1
printfn "%b" isEmpty2

解説:

List.isEmpty 関数は、与えられたリストが空であれば true を、そうでなければ false を返す。list1 は空リストなので truelist2 は要素を含むので false が返される。

問題7: リストの長さを取得する

入力:

  • [1; 2; 3; 4; 5]

出力:

  • 5
ヒント
  • List.length 関数を使用する
解答例と解説
let list = [1; 2; 3; 4; 5]
let length = List.length list
printfn "%d" length

解説:

List.length 関数はリストの要素数を返す。この例では、list は5つの要素を持つため、length5 になる。

問題8: リストのパターンマッチング

入力:

  • [1; 2; 3]

出力:

  • head: 1
  • tail: [2; 3]
ヒント
  • match ... with 構文を使用する
解答例と解説
let list = [1; 2; 3]
match list with
| head :: tail ->
printfn "head: %d" head
printfn "tail: %A" tail
| [] -> printfn "empty list"

解説:

match ... with 構文を使うと、リストの構造に基づいてパターンマッチングを行うことができる。head :: tail というパターンは、リストの先頭要素を head、残りのリストを tail に束縛する。空リストの場合は [] というパターンにマッチする。

問題9: リストの要素を逆順にする

入力:

  • [1; 2; 3; 4; 5]

出力:

  • [5; 4; 3; 2; 1]
ヒント
  • List.rev 関数を使用する
解答例と解説
let list = [1; 2; 3; 4; 5]
let reversedList = List.rev list
printfn "%A" reversedList

解説:

List.rev 関数は、リストの要素を逆順にした新しいリストを返す。この例では、reversedList[5; 4; 3; 2; 1] となる。

問題10: リストの各要素に関数を適用し、新しいリストを作成する

入力:

  • [1; 2; 3]
  • 適用する関数: 要素を2倍する関数

出力:

  • [2; 4; 6]
ヒント
  • List.map 関数を使用する
  • 類似関数として List.mapi (インデックス付き)、List.map2List.map3 (それぞれ2つ、3つのリストを扱う) がある
解答例と解説
let list = [1; 2; 3]
let doubledList = List.map (fun x -> x * 2) list
printfn "%A" doubledList

解説:

List.map 関数は、リストの各要素に関数を適用し、その結果からなる新しいリストを作成する。この例では、fun x -> x * 2 という関数を使って各要素を2倍にしている。doubledList[2; 4; 6] となる。 List.mapi は、要素だけでなくインデックスも関数に渡す場合に使う。List.map2List.map3 は、それぞれ2つと3つのリストの対応する要素に関数を適用する。

問題11: リストの各要素に対して副作用のある操作を実行する

入力:

  • ["a"; "b"; "c"]

出力:

  • a (改行)
  • b (改行)
  • c (改行)
ヒント
  • List.iter 関数を使用する
  • 類似関数として List.iteri (インデックス付き)、List.iter2List.iter3 (それぞれ2つ、3つのリストを扱う) がある
解答例と解説
let list = ["a"; "b"; "c"]
List.iter (printfn "%s") list

解説:

List.iter 関数は、リストの各要素に対して指定された関数を適用する。List.map とは異なり、戻り値はない (つまり、unit 型を返す)。主に副作用のある操作を実行するために使用される。この例では、printfn "%s" という関数を使って各要素を表示している。 List.iteri は、要素だけでなくインデックスも関数に渡す場合に使う。List.iter2List.iter3 は、それぞれ2つと3つのリストの対応する要素に関数を適用する。

問題12: リストから条件を満たす要素のみを抽出する

入力:

  • [1; 2; 3; 4; 5; 6]
  • 条件: 偶数

出力:

  • [2; 4; 6]
ヒント
  • List.filter 関数を使用する
  • List.filteri はインデックス付きで要素をフィルタリングする
解答例と解説
let list = [1; 2; 3; 4; 5; 6]
let evenNumbers = List.filter (fun x -> x % 2 = 0) list
printfn "%A" evenNumbers

解説:

List.filter 関数は、リストの各要素に条件を適用し、true を返す要素のみを含む新しいリストを作成する。この例では、fun x -> x % 2 = 0 という関数を使って、各要素 x が偶数かどうかを判定している。evenNumbers[2; 4; 6] となる。List.filteri を使うと、要素のインデックスも考慮したフィルタリングができる。

問題13: リストのすべての要素が条件を満たすかどうかを判定する

入力:

  • [2; 4; 6; 8]
  • 条件: 偶数

出力:

  • true
ヒント
  • List.forall 関数を使用する
解答例と解説
let list = [2; 4; 6; 8]
let areAllEven = List.forall (fun x -> x % 2 = 0) list
printfn "%b" areAllEven

解説:

List.forall 関数は、リストのすべての要素が指定された条件を満たす場合に true を、そうでない場合に false を返す。この例では、fun x -> x % 2 = 0 という関数を使って、各要素 x が偶数かどうかを判定している。list のすべての要素は偶数なので、areAllEventrue になる。

問題14: リストの少なくとも1つの要素が条件を満たすかどうかを判定する

入力:

  • [1; 3; 5; 6; 7]
  • 条件: 偶数

出力:

  • true
ヒント
  • List.exists 関数を使用する
  • List.exists2 関数は2つのリストを扱う
解答例と解説
let list = [1; 3; 5; 6; 7]
let existsEven = List.exists (fun x -> x % 2 = 0) list
printfn "%b" existsEven

解説:

List.exists 関数は、リストの少なくとも1つの要素が指定された条件を満たす場合に true を、そうでない場合に false を返す。この例では、fun x -> x % 2 = 0 という関数を使って、各要素 x が偶数かどうかを判定している。list には偶数 6 が含まれているので、existsEventrue になる。List.exists2 は、2つのリストの対応する要素が条件を満たすかどうかを判定する。

問題15: リストから条件を満たす要素を検索する

入力:

  • [1; 3; 4; 5; 6]
  • 条件: 3の倍数

出力:

  • 6
ヒント
  • List.find 関数を使用する
  • 似た関数として以下のようなものがある:
    • List.tryFind: Option 型で結果を返す
    • List.findBack / List.tryFindBack: リストを後方から検索する
    • List.findIndex / List.tryFindIndex: 条件を満たす要素のインデックスを返す
    • List.findIndexBack / List.tryFindIndexBack: リストを後方から検索してインデックスを返す
解答例と解説
let list = [1; 3; 4; 5; 6]
let foundElement = List.find (fun x -> x % 3 = 0) list
printfn "%d" foundElement

解説:

List.find 関数は、リストの先頭から要素を調べ、指定された条件を満たす最初の要素を返す。この例では、fun x -> x % 3 = 0 という関数を使って、3の倍数を見つけようとしている。最初に見つかる3の倍数は 6 なので、foundElement6 になる。 List.tryFind は、条件を満たす要素が見つからなかった場合に例外を発生させる代わりに None を返す。List.findBackList.tryFindBack はリストを後方から検索する。List.findIndex, List.tryFindIndex, List.findIndexBack, List.tryFindIndexBack は、要素そのものではなく、そのインデックスを返す。

これで基礎編の15問が完成しました。`List.tryFind`, `List.findBack`, `List