Skip to content

F# List標準問題精講

この文書は、F#のリストの様々な関数を使いこなすための練習問題集のPart 3 (上級編) である。15問を通して、F#のリスト操作の上級レベルの技術をマスターすることを目指す。

問題36: 2つのリストを結合する (@ 演算子, List.append)

入力:

  • [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] を返す。この問題は基礎編の問題3と同じだが、上級編では List.append@ 演算子の別名であることを理解していることを前提としている。

問題37: リストのリストを1つのリストに結合する

入力:

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

出力:

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

解説:

List.concat 関数は、リストのリストを受け取り、それらを1つのリストに結合する。この例では、concatenatedList[1; 2; 3; 4; 5; 6] となる。

問題38: あるリストから別のリストに含まれる要素を除外する

入力:

  • リスト1: [1; 2; 3; 4; 5; 6]
  • リスト2: [2; 4; 6]

出力:

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

解説:

List.except 関数は、第1引数のリストから、第2引数のリストに含まれる要素を除外した新しいリストを返す。この例では、list1 から list2 に含まれる要素 246 が除外され、result[1; 3; 5] となる。

問題39: リストの先頭の要素を取得する (List.head の例外処理)

入力:

  • [1; 2; 3]

出力:

  • 1

備考:

  • List.head は空リストに対して例外を発生させるため、適切に処理すること
ヒント
  • List.tryHead 関数を使用する、または List.headtry...with 構文で囲む
解答例と解説
let list = [1; 2; 3]
// List.tryHead を使う場合
let tryHeadResult = List.tryHead list
match tryHeadResult with
| Some head -> printfn "%d" head
| None -> printfn "List is empty"
// List.head を try...with で囲む場合
try
let head = List.head list
printfn "%d" head
with
| :? System.ArgumentException -> printfn "List is empty"

解説:

List.head 関数はリストの先頭の要素を返す。ただし、空リストに適用すると例外が発生する。そのため、安全に扱うには List.tryHead 関数を使用するか、List.headtry...with 構文で囲んで例外をキャッチする必要がある。

  • List.tryHead は、リストが空であれば None を、そうでなければ Some でラップされた先頭要素を返す。
  • try...with 構文を使うと、List.head が発生させる System.ArgumentException をキャッチして、適切な処理を行うことができる。

この例では、どちらの方法でも 1 が出力される。

問題40: リストの先頭を除いた残りのリストを取得する (List.tail の例外処理)

入力:

  • [1; 2; 3]

出力:

  • [2; 3]

備考:

  • List.tail は空リストに対して例外を発生させるため、適切に処理すること
ヒント
  • リストが空かどうかを List.isEmpty で判定し、条件分岐する
解答例と解説
let list = [1; 2; 3]
if List.isEmpty list then
printfn "List is empty"
else
let tailList = List.tail list
printfn "%A" tailList

解説:

List.tail 関数はリストの先頭を除いた残りのリストを返す。ただし、空リストに適用すると例外が発生する。そのため、安全に扱うには、事前に List.isEmpty でリストが空かどうかを判定し、条件分岐する必要がある。

この例では、list は空ではないため、List.tail が適用され、[2; 3] が出力される。

問題41: リストの指定されたインデックスの要素を取得する (List.item / List.nth の例外処理)

入力:

  • [1; 2; 3]
  • インデックス: 1

出力:

  • 2

備考:

  • List.item / List.nth はインデックスが範囲外の場合に例外を発生させるため、適切に処理すること
ヒント
  • List.tryItem 関数を使用する、または List.item / List.nthtry...with 構文で囲む
解答例と解説
let list = [1; 2; 3]
let index = 1
// List.tryItem を使う場合
let tryItemResult = List.tryItem index list
match tryItemResult with
| Some item -> printfn "%d" item
| None -> printfn "Index out of range"
// List.nth を try...with で囲む場合 (List.item も同様)
try
let item = List.nth index list
printfn "%d" item
with
| :? System.ArgumentOutOfRangeException -> printfn "Index out of range"

解説:

List.itemList.nth 関数はどちらも、リストの指定されたインデックスの要素を返す。ただし、インデックスが範囲外の場合に例外が発生する。そのため、安全に扱うには List.tryItem 関数を使用するか、List.item / List.nthtry...with 構文で囲んで例外をキャッチする必要がある。

  • List.tryItem は、インデックスが範囲外であれば None を、そうでなければ Some でラップされた要素を返す。
  • try...with 構文を使うと、List.item / List.nth が発生させる System.ArgumentOutOfRangeException をキャッチして、適切な処理を行うことができる。

この例では、どちらの方法でも 2 が出力される。

問題42: リストの最後の要素を取得する (List.last の例外処理)

入力:

  • [1; 2; 3]

出力:

  • 3

備考:

  • List.last は空リストに対して例外を発生させるため、適切に処理すること
ヒント
  • List.tryLast 関数を使用する、または List.lasttry...with 構文で囲む
解答例と解説
let list = [1; 2; 3]
// List.tryLast を使う場合
let tryLastResult = List.tryLast list
match tryLastResult with
| Some last -> printfn "%d" last
| None -> printfn "List is empty"
// List.last を try...with で囲む場合
try
let last = List.last list
printfn "%d" last
with
| :? System.ArgumentException -> printfn "List is empty"

解説:

List.last 関数はリストの最後の要素を返す。ただし、空リストに適用すると例外が発生する。そのため、安全に扱うには List.tryLast 関数を使用するか、List.lasttry...with 構文で囲んで例外をキャッチする必要がある。

  • List.tryLast は、リストが空であれば None を、そうでなければ Some でラップされた最後の要素を返す。
  • try...with 構文を使うと、List.last が発生させる System.ArgumentException をキャッチして、適切な処理を行うことができる。

この例では、どちらの方法でも 3 が出力される。

問題43: 配列をリストに変換する

入力:

  • [|1; 2; 3|]

出力:

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

解説:

List.ofArray 関数は、配列をリストに変換する。この例では、list[1; 2; 3] となる。

問題44: シーケンスをリストに変換する

入力:

  • seq { 1; 2; 3 }

出力:

  • [1; 2; 3]
ヒント
  • List.ofSeq 関数を使用する
解答例と解説
let sequence = seq { 1; 2; 3 }
let list = List.ofSeq sequence
printfn "%A" list

解説:

List.ofSeq 関数は、シーケンスをリストに変換する。この例では、list[1; 2; 3] となる。

問題45: リストを配列に変換する

入力:

  • [1; 2; 3]

出力:

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

解説:

List.toArray 関数は、リストを配列に変換する。この例では、array[|1; 2; 3|] となる。

問題46: リストをシーケンスに変換する

入力:

  • [1; 2; 3]

出力:

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

解説:

List.toSeq 関数は、リストをシーケンスに変換する。この例では、sequenceseq [1; 2; 3] となる。

問題47: リスト内包表記を使って、1から10までの偶数のリストを作成する

入力:

  • なし

出力:

  • [2; 4; 6; 8; 10]
ヒント
  • リスト内包表記を使用する
  • for ループと if 条件を組み合わせる
解答例と解説
let evenNumbers = [ for i in 1 .. 10 do if i % 2 = 0 then yield i ]
printfn "%A" evenNumbers

解説:

リスト内包表記を使うと、簡潔な記法でリストを生成できる。for ループで i1 から 10 まで変化させ、if i % 2 = 0i が偶数の場合のみ yield i でリストに要素を追加する。結果として、evenNumbers[2; 4; 6; 8; 10] となる。

問題48: リスト内包表記を使って、リストの各要素を2乗したリストを作成する

入力:

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

出力:

  • [1; 4; 9; 16; 25]
ヒント
  • リスト内包表記を使用する
  • for ループと yield を組み合わせる
解答例と解説
let list = [1; 2; 3; 4; 5]
let squaredList = [ for x in list do yield x * x ]
printfn "%A" squaredList

解説:

リスト内包表記の for x in listlist の各要素 x を取り出し、yield x * xx の2乗をリストに追加する。結果として、squaredList[1; 4; 9; 16; 25] となる。

問題49: リストの先頭の要素を Option 型で取得する (List.tryHead)

入力:

  • [1; 2; 3]
  • []

出力:

  • Some 1
  • None
ヒント
  • List.tryHead 関数を使用する
解答例と解説
let list1 = [1; 2; 3]
let list2 = []
let tryHeadResult1 = List.tryHead list1
let tryHeadResult2 = List.tryHead list2
printfn "%A" tryHeadResult1
printfn "%A" tryHeadResult2

解説:

List.tryHead 関数は、リストの先頭の要素を Option 型で返す。リストが空でない場合は Some でラップされた先頭要素を、空の場合は None を返す。 この例では、tryHeadResult1Some 1tryHeadResult2None となる。List.head とは異なり、空リストに対して例外を発生させないため、安全に扱うことができる。

問題50: リストの最後の要素を Option 型で取得する (List.tryLast)

入力:

  • [1; 2; 3]
  • []

出力:

  • Some 3
  • None
ヒント
  • List.tryLast 関数を使用する
解答例と解説
let list1 = [1; 2; 3]
let list2 = []
let tryLastResult1 = List.tryLast list1
let tryLastResult2 = List.tryLast list2
printfn "%A" tryLastResult1
printfn "%A" tryLastResult2

解説:

List.tryLast 関数は、リストの最後の要素を Option 型で返す。リストが空でない場合は Some でラップされた最後の要素を、空の場合は None を返す。この例では、tryLastResult1Some 3tryLastResult2None となる。List.last とは異なり、空リストに対して例外を発生させないため、安全に扱うことができる。