6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

こんなにあった... F#ドキュメントには未掲載のArray関数

Posted at
  • ※以下はF#のドキュメントが更新されれば不必要になるでしょう。
  • 前置きをスキップするときは「Arrayモジュールの未掲載関数」からお読みください。

F#はMicrosoftのDon Syme氏が開発したプログラミング言語で、命令型、オブジェクト指向、関数型の要素を併せ持つマルチパラダイム言語と位置付けられています。実装はオープンソースのMITライセンスのもと、githubのリポジトリで公開されています。

実行環境は.NET Frameworkおよび.NET CoreやMonoといったマルチプラットフォームに対応していますが、サポート状況については各プラットフォームごとの情報を参照してください(「F# の概要」など)。

なお、ここで対象とするF#のバージョンは4.1(FSharp.Core 4.4.1.0)とします。

Arrayについて

Arrayは同じ型の複数の要素を同時に扱える(1次元)__配列__という型に対して実行できる関数が定義されたモジュールの名称です。配列の型名は'T []もしくはarray<'T>(いずれも'Tは要素の型)で表します。各要素は両端を[|~|]で囲んだ中に;(セミコロン)で区切って設定します。

配列の要素は定数やforで設定できます。intcharなど..(範囲指定)で設定できる型もあります。

配列の要素を設定
[|'a'; 'b'; 'c'; 'd'; 'e'|]  // 定数による設定
[|for c in 'a'..'e' -> c|]   // forによる設定 ([|'a'; 'b'; 'c'; 'd'; 'e'|])
[|'a'..'e'|]    // 範囲指定による設定 ([|'a'; 'b'; 'c'; 'd'; 'e'|])

配列からは、特定の位置もしくは範囲にある要素のみを取り出せます。位置は先頭が.[0]でそれ以降.[1], .[2], ...と表します。範囲は.[1..3]などと表します。[..3][2..]のように範囲の始点や終点を明示しない場合は、それぞれ先頭や末尾とみなされます。

配列から特定の位置の要素を取り出す
let a = [|'a'..'e'|]  // [|'a'; 'b'; 'c'; 'd'; 'e'|]
a.[2]     // 'c'
a.[1..3]  // [|'b'; 'c'; 'd'|]
a.[2..]   // [|'c'; 'd'; 'e'|]
a.[..3]   // [|'a'; 'b'; 'c'; 'd'|]

配列の型は.NETのSystem.Arrayクラスによるものなので、このクラスのプロパティやメソッドに対応しています。

配列の型
let a = [|'a'..'e'|]  // [|'a'; 'b'; 'c'; 'd'; 'e'|]

(* System.Arrayのプロパティやメソッドに対応 *)
a.Length  // 5
a.GetValue 2  // 'c'
System.Array.IndexOf(a, 'c')  // 2

(* リフレクションで型を確認 *)
a.GetType().FullName  // System.Char[]
a.GetType().BaseType.FullName  // System.Array
a.GetType().GetElementType().FullName  // System.Char

Arrayモジュールの未掲載関数

F#では、System.Arrayクラスとは別にArrayモジュールで多くの関数を定義済みです。ただ、2017年8月18日更新分のドキュメントには、定義されたすべての関数が掲載されているわけではありません。そこで、ここからはこのドキュメントに掲載されていない__未掲載関数__を紹介していきます。

Array.chunkBySize 要素数 配列
int -> 'T [] -> 'T [] []

一次元配列の要素を指定された数ごとに区切ったジャグ配列(配列の配列)を得られます。要素数は正の整数でないときはSystem.ArgumentExceptionが発生します。要素数が配列より大きくても例外は発生しません。

Array.chunkBySize
Array.chunkBySize  3 [|0..7|]  // [|[|0; 1; 2|]; [|3; 4; 5|]; [|6; 7|]|] : int [] []
Array.chunkBySize  0 [|0..7|]  // 例外発生「System.ArgumentException: 入力は正である必要があります。」
Array.chunkBySize<int> 3 [||]  // [||] : int [] []

Array.distinctBy 関数 配列
(('T -> 'U) -> 'T [] -> 'T []) when 'U : equality

配列の各要素を引数にして関数を実行し、その結果の配列から重複をなくしたものを得られます。要素のない空の配列でも例外は発生しません。

Array.distinctBy
Array.distinctBy (fun n -> n % 2) [|1; 3; 0; 2|]  // [|1; 0|]
Array.distinctBy<int, bool> (fun _ -> true) [||]  // [||] : int []

Array.exactlyOne 要素1つだけの配列
'T [] -> 'T

要素が1つだけの配列から要素を取り出します。配列の要素が複数もしくは空のときはSystem.ArgumentExceptionが発生します。逆のはたらきをするArray.singletonもあります。

Array.exactlyOne
Array.exactlyOne [|3|]      // 3 (Array.singletonとは逆)
Array.exactlyOne [|3; 2|]   // 例外発生「System.ArgumentException: 入力シーケンスに複数の要素が含まれています。」
Array.exactlyOne<int> [||]  // 例外発生「System.ArgumentException: 入力シーケンスが空でした。」

Array.singleton 3  // [|3|] (Array.exactlyOneとは逆)

Array.except 配列1 配列2
(seq<'T> -> 'T [] -> 'T []) when 'T : equality

配列2の要素から配列1の要素を取り除いた配列を得られます。配列1はlist, seq, setにも対応します。どちらの配列が空でも例外は発生しません。

Array.except
Array.except [|2; 1|] [|3; 2; 5; 4; 1|]  // [|3; 5; 4|]  第1引数はlist, seq, setでも良い
Array.except<int> [||] [||]  // [||] : int []

Array.findBack 関数 配列
('T -> bool) -> 'T [] -> 'T

配列の要素を引数にして関数を順次実行し、その結果(bool型)が最初にtrueとなった要素を得られます。要素が見つからないときはSystem.Collections.Generic.KeyNotFoundExceptionという例外が発生します。結果がoptionになるArray.tryFindBackや、配列の要素を先頭から順次判定していくArray.findも定義されています。

Array.findBack
Array.findBack (fun n -> n % 2 = 1) [|1; 2; 3|]  // 3
Array.findBack (fun n -> n % 2 = 1) [|0|]  // 例外発生「System.Collections.Generic.KeyNotFoundException」

Array.tryFindBack (fun n -> n % 2 = 1) [|1; 2; 3|]  // Some 3

Array.find        (fun n -> n % 2 = 1) [|1; 2; 3|]  // 1

Array.findIndexBack
('T -> bool) -> 'T [] -> int

Array.findBackの結果がある要素の位置を得られます。要素が見つからないときはSystem.Collections.Generic.KeyNotFoundExceptionが発生します。結果がoptionになるArray.tryFindIndexBackや、配列の要素を先頭から判定していくArray.findIndexもあります。

Array.findIndexBack
Array.findIndexBack (fun n -> n % 2 = 1) [|1; 2; 3|]  // 2
Array.findIndexBack (fun n -> n % 2 = 1) [|0|]  // 例外発生「System.Collections.Generic.KeyNotFoundException」

Array.tryFindIndexBack (fun n -> n % 2 = 1) [|1; 2; 3|]  // Some 2
Array.findIndex (fun n -> n % 2 = 1) [|1; 2; 3|]  // 0

Array.groupBy 関数 配列
(('T -> 'U) -> 'T [] -> ('U * 'T []) []) when 'U : equality

配列の要素を引数とする関数を順次実行し、その結果ごとに要素をグループ分けします。結果となる配列の要素は(関数の結果, [|要素, ...|])となります。引数の配列が空でも例外は発生しません。

Array.groupBy
Array.groupBy (fun n -> n % 3) [|0..7|]  // [|(0, [|0; 3; 6|]); (1, [|1; 4; 7|]); (2, [|2; 5|])|]
Array.groupBy (fun n -> n % 3) [||]  // [||] : (int * int []) []

Array.head 配列
('T [] -> 'T)

配列の先頭の要素を得られます。配列要素が空のときはSystem.ArgumentExceptionが発生します。結果がoptionになるArray.tryHeadもあります。また、配列の先頭の要素だけをなくした配列を得るArray.tailや、配列の末尾の要素を得るArray.lastArray.tryLastもあります。

Array.head
Array.head [|3; 1; 2|]  // 3
Array.head<int> [||]    // 例外発生「System.ArgumentException: 入力配列が空でした。」

Array.tryHead [|3; 1; 2|]  // Some 3
Array.tryHead<int> [||]    // None

Array.tail [|3; 1; 2|]     // [|1; 2|]

Array.last [|3; 1; 2|]     // 2
Array.tryLast [|3; 1; 2|]  // Some 2
Array.tryLast<int> [||]    // None

Array.indexed 配列
'T [] -> (int * 'T) []

配列の要素とその位置を(位置, 要素)という1つのタプルに収めた要素を持つ配列を得られます。配列の要素が空でも例外は発生しません。

Array.indexed
Array.indexed [|'a'..'c'|]  // [|(0, 'a'); (1, 'b'); (2, 'c')|]
Array.indexed<char> [||]    // [||] : (int * char) []

Array.item 位置 配列
int -> 'T [] -> 'T

配列から指定した位置の要素を得られます。指定した位置に要素が存在しなければSystem.IndexOutOfRangeExceptionが発生します。結果がoptionになるArray.tryItemもあります。

Array.item
Array.item      2 [|'c'; 'a'; 'b'|]  // 'b'
Array.item<int> 1 [||]  // 例外発生「System.IndexOutOfRangeException: インデックスが配列の境界外です。」

Array.tryItem      2 [|'c'; 'a'; 'b'|]  // Some 'b'
Array.tryItem<int> 0 [||]  // None

Array.last 配列
'T [] -> 'T

配列の末尾の要素を得られます。配列の要素が空のときはSystem.ArgumentExceptionが発生します。結果がoptionになるArray.tryLastもあります。また、配列の先頭の要素を得られるArray.headArray.tryHeadもあります。

Array.last
Array.last      [|3; 1; 2|]  // 2
Array.last<int> [||]  // 例外発生「System.ArgumentException: 入力配列が空でした。」

Array.tryLast [|3; 1; 2|]  // Some 2
Array.tryLast<int> [||]    // None

Array.head    [|3; 1; 2|]  // 3
Array.tryHead [|3; 1; 2|]  // Some 3

Array.map3 関数 配列1 配列2 配列3
('T -> 'U -> 'V -> 'W) -> 'T [] -> 'U [] -> 'V [] -> 'W []

同じ数の要素を持つ3つの配列のそれぞれから順次取り出した要素を引数とする関数を実行し、その結果を要素とする配列を得られます。それぞれの配列の要素の型が違っていても対応しますが、3つの配列の要素の数がどれか1つでも違っているとSystem.ArgumentExceptionが発生します。

Array.map3
Array.map3 (fun x y z -> (x, y, z)) [|0..2|] [|'a'..'c'|] [|'$'..'&'|]
// [|(0, 'a', '$'); (1, 'b', '%'); (2, 'c', '&')|]
Array.map3 (fun x y z -> (x, y, z)) [|0..2|] [|'a'..'d'|] [|'$'..'&'|]
// 例外発生「System.ArgumentException: 配列の長さが異なります。」

Array.mapFold 関数 初期値 配列
('T -> 'U -> 'V * 'T) -> 'T -> 'U [] -> 'V [] * 'T

初期値に対して配列の要素を関数で累積的に処理していった途中経過と最終的な結果をタプルで得られます。関数の引数を、初期値もしくは前回の処理結果と、配列の先頭から順次取り出される要素の2つとし、戻り値は(最終結果のタプルの左側の要素, 次回関数実行時の第1引数)とします。配列の要素を末尾から取り出すArray.mapFoldBackもありますが、引数の位置などに違いがありますので注意してください。

Array.mapFold
Array.mapFold (fun x y ->
  printfn "x = %2d, y = %1d, x * y = %3d" x y (x * y)
  (x, x * y)) 1 [|2..5|]
(* 途中経過 *)
x =  1, y = 2, x * y =   2
x =  2, y = 3, x * y =   6
x =  6, y = 4, x * y =  24
x = 24, y = 5, x * y = 120
(* 最終結果 *)
([|1; 2; 6; 24|], 120)

Array.mapFoldBack (fun x y -> (x, x * y)) [|2..5|] 1
// ([|2; 3; 4; 5|], 120)

Array.mapFoldBack 関数 配列 初期値
('T -> 'U -> 'V * 'U) -> 'T [] -> 'U -> 'V [] * 'U

初期値に対して配列の要素を関数で累積的に処理していった途中経過と最終結果をタプルで得られます。関数の引数は、配列の末尾から順次取り出される要素と、初期値もしくは前回の処理結果の2つとし、戻り値は(最終結果左側の配列の要素, 次回関数実行時の第2引数)とします。最終結果の配列の要素は、先に関数から得られたものほど後に配置されます。配列の要素を先頭から順次取り出すArray.mapFoldもありますが、引数の位置などに違いがありますので注意してください。

Array.mapFoldBack
Array.mapFoldBack (fun x y ->
  printfn "x = %1d, y = %2d, x * y = %3d" x y (x * y)
  (y, x * y)) [|2..5|] 1

(* 途中経過 *)
x = 5, y =  1, x * y =   5
x = 4, y =  5, x * y =  20
x = 3, y = 20, x * y =  60
x = 2, y = 60, x * y = 120

(* 最終結果 *)
([|60; 20; 5; 1|], 120)

Array.pairwise配列
'T [] -> ('T * 'T) []

隣り合う要素どうしをタプル収めた要素を持つ配列を得られます。配列の要素が1つ以下のときの戻り値は空の配列となります。

Array.pairwise
Array.pairwise [|'a'..'d'|]  // [|('a', 'b'); ('b', 'c'); ('c', 'd')|]

Array.pairwise [|'a'|]       // [||] : (char * char) []
Array.pairwise<char> [||]    // [||] : (char * char) []

Array.replicate 数値 要素
int -> 'T -> 'T []

同じ値の要素を複数持つ配列を得られます。数値が0以上の整数でなければはSystem.ArgumentExceptionが発生します。

Array.replicate
Array.replicate  3 "F#"  // [|"F#"; "F#"; "F#"|]
Array.replicate -1 "F#"  // 例外発生「System.ArgumentException: 入力は負以外である必要があります。」

Array.singleton 要素
'T -> 'T []

要素を1つだけ持つ配列を得られます。逆に要素が1つだけの配列から要素を取り出すArray.exactlyOneもあります。

Array.singleton
Array.singleton 3       // [|3|]
Array.exactlyOne [|3|]  // 3

Array.skip 数値 配列
int -> 'T [] -> 'T []

先頭から指定した位置までの要素をなくした配列を得られます。数値が負の数でも例外は発生しません。逆に先頭から指定した位置までの要素を持つ配列を得られるArray.takeもあります。

Array.skip
Array.skip  2 [|'a'..'e'|]  // [|'c'; 'd'; 'e'|]
Array.skip -1 [|'a'..'e'|]  // [|'a'; 'b'; 'c'; 'd'; 'e'|]

Array.take 3 [|'a'..'e'|]  // [|'a'; 'b'; 'c'|]

Array.skipWhile 関数 配列
('T -> bool) -> 'T [] -> 'T []

関数の戻り値がfalseとなる位置までの要素をなくした配列を得られます。逆にその位置までの要素を得られるArray.takeWhileもあります。

Array.skipWhile
Array.skipWhile (fun n -> n < 4) [|3; 2; 5; 4; 1|]  // [|5; 4; 1|]

Array.takeWhile (fun n -> n < 4) [|3; 2; 5; 4; 1|]  // [|3; 2|]

Array.sortByDescending 関数 配列
(('T -> 'U) -> 'T [] -> 'T []) when 'U : comparison

配列の要素を引数とする関数を順次実行した結果をもとに要素を降順で並べ替えます。関数の結果は比較可能な値でなければなりません。他に配列の要素自体を並べ替えるArray.sortDescendingや、配列の並べ替えが昇順になるArray.sortByもあります。

Array.sortByDescending
Array.sortByDescending (fun (x, _) -> x) [|(2, "dos"); (3, "tres"); (1, "uno")|]
// [|(3, "tres"); (2, "dos"); (1, "uno")|]

Array.sortDescending [|2; 3; 1; 5; 4|]
// [|5; 4; 3; 2; 1|]

Array.sortBy (fun (x, _) -> x) [|(2, "dos"); (3, "tres"); (1, "uno")|]
// [|(1, "uno"); (2, "dos"); (3, "tres")|]

Array.sortDescending 配列
('T [] -> 'T []) when 'T : comparison

配列の要素を降順で並べ替えます。要素は比較可能な値でなければなりません。他に昇順で並べ替えるArray.sortや要素を引数にして関数を順次実行した値で並べ替えるArray.sortByDescendingもあります。

Array.sortDescending
Array.sortDescending [|2; 3; 1; 5; 4|]  // [|5; 4; 3; 2; 1|]

Array.sort [|2; 3; 1; 5; 4|]  // [|1; 2; 3; 4; 5|]

Array.sortByDescending (fun (x, _) -> x) [|(2, "dos"); (3, "tres"); (1, "uno")|]
// [|(3, "tres"); (2, "dos"); (1, "uno")|]

Array.splitAt 位置 配列
int -> 'T [] -> 'T [] * 'T []

指定した要素の位置ので配列を2つに分け、それぞれを同じタプルに収めます。指定された位置の要素はタプルの右側の配列に含まれます。位置は0か正の整数に限られ、それ以外を指定するとSystem.ArgumentExceptionが発生します。また、指定した位置が配列の長さ(要素の数)より大きいとSystem.InvalidOperationExceptionが発生します。

Array.splitAt
Array.splitAt  3 [|'a'..'e'|]  // ([|'a'; 'b'; 'c'|], [|'d'; 'e'|])
Array.splitAt  0 [|'a'..'e'|]  // ([||], ([||], [|'a'; 'b'; 'c'; 'd'; 'e'|]))
Array.splitAt  5 [|'a'..'e'|]  // ([|'a'; 'b'; 'c'; 'd'; 'e'|], [||])

Array.splitAt -1 [|'a'..'e'|]  // 例外発生「System.ArgumentException: 入力は負以外である必要があります。」
Array.splitAt  6 [|'a'..'e'|]  // 例外発生「System.InvalidOperationException: 入力シーケンスには十分な数の要素がありません。」

Array.splitInto 分割数 配列
int -> 'T [] -> 'T [] []

配列の要素を指定した数に等分します。結果は'T [] []になります。分割数が0のときはSystem.ArgumentExceptionが発生します。分割数が配列の要素の数より大きくても例外は発生しません。

Array.splitInto
Array.splitInto 3 [|'a'..'e'|]  // [|[|'a'; 'b'|]; [|'c'; 'd'|]; [|'e'|]|] : char [] []
Array.splitInto 0 [|'a'..'e'|]  // 例外発生「System.ArgumentException: 入力は正である必要があります。」
Array.splitInto 3 [|'a'; 'b'|]  // [|[|'a'|]; [|'b'|]|]

Array.tail 配列
'T [] -> 'T []

先頭の要素をなくした配列を得られます。配列の要素がないときはSystem.ArgumentExceptionが発生します。逆に配列の先頭の要素だけを得られるArray.headもあります。

Array.tail
Array.tail [|3; 1; 2|]  // [|1; 2|]
Array.tail<int> [||]    // 例外発生「System.ArgumentException: 入力シーケンスには十分な数の要素がありません。」

Array.head [|3; 1; 2|]  // 3

Array.take 要素数 配列
int -> 'T [] -> 'T []

先頭から指定された数だけの要素を持つ配列を得られます。要素数が負の数のときはSystem.ArgumentExceptionが発生します。また、要素数が配列の長さより大きいときはSystem.InvalidOperationExceptionが発生します。他に関数で判定した位置の要素を持つ配列を得られるArray.takeWhileや、逆に先頭から指定された数の要素をなくした配列を得られるArray.skipもあります。

Array.take
Array.take  3 [|'a'..'e'|]  // [|'a'; 'b'; 'c'|]
Array.take  0 [|'a'..'e'|]  // [||] : char []
Array.take -1 [|'a'..'e'|]  // 例外発生「System.ArgumentException: 入力は負以外である必要があります。」
Array.take  6 [|'a'..'e'|]  // 例外発生「System.InvalidOperationException: 入力シーケンスには十分な数の要素がありません。」

Array.takeWhile (fun n -> n < 4) [|3; 2; 5; 4; 1|]  // [|3; 2|]

Array.skip  3 [|'a'..'e'|]  // [|'d'; 'e'|]

Array.takeWhile 関数 配列
('T -> bool) -> 'T [] -> 'T []

要素を引数とする関数を先頭から順次実行し、結果がtrueとなる要素を持つ配列を得られます。逆に結果がfalseとなる位置から末尾までの要素を持つ配列を得られるArray.skipWhileや、先頭から指定した位置までの要素を持つ配列を得られるArray.takeもあります。

Array.takeWhile
Array.takeWhile (fun n -> n < 4) [|3; 2; 5; 4; 1|]  // [|3; 2|]

Array.skipWhile (fun n -> n < 4) [|3; 2; 5; 4; 1|]  // [|5; 4; 1|]

Array.take  3 [|3; 2; 5; 4; 1|]  // [|3; 2; 5|]

Array.truncate 要素数 配列
int -> 'T [] -> 'T []

先頭から指定した数だけの要素を持つ配列を得られます。Array.takeと違うのは、要素数に関連する例外が発生しないところです。

Array.truncate
Array.truncate  3 [|3; 2; 5; 4; 1|]  // [|3; 2; 5|]
Array.take      3 [|3; 2; 5; 4; 1|]  // [|3; 2; 5|]

(* 要素数が配列の長さより大きいとき *)
Array.truncate  6 [|3; 2; 5; 4; 1|]  // [|3; 2; 5; 4; 1|]
Array.take      6 [|3; 2; 5; 4; 1|]  // 例外発生「System.InvalidOperationException: 入力シーケンスには十分な数の要素がありません。」

(* 要素数が負の数のとき *)
Array.truncate -1 [|3; 2; 5; 4; 1|]  // [||] : int []
Array.take     -1 [|3; 2; 5; 4; 1|]  // 例外発生「System.ArgumentException: 入力は負以外である必要があります。」

Array.tryFindBack 関数 配列
('T -> bool) -> 'T [] -> 'T option

末尾の要素から順次関数を実行し、結果がtrueとなる要素を見つけます。結果は、見つかったらSome 結果、見つからなかったらNoneとなります。結果がoptionではないArray.findBackもあるほか、先頭の要素から順に関数を実行するArray.tryFindArray.findもあります。

Array.tryFindBack
(* 結果が見つかったとき *)
Array.tryFindBack (fun n -> n % 2 = 1) [|1; 2; 3|]  // Some 3
Array.findBack    (fun n -> n % 2 = 1) [|1; 2; 3|]  // 3

(* 結果が見つからないとき *)
Array.tryFindBack (fun n -> n > 3) [|1; 2; 3|]  // None
Array.findBack    (fun n -> n > 3) [|1; 2; 3|]  // 例外発生「System.Collections.Generic.KeyNotFoundException」

Array.tryFind (fun n -> n % 2 = 1) [|1; 2; 3|]  // Some 1
Array.find    (fun n -> n % 2 = 1) [|1; 2; 3|]  // 1

Array.tryFindIndexBack 関数 配列
('T -> bool) -> 'T [] -> int option

Array.tryFindBackの結果となる要素の位置を見つけます。結果は、見つかったらSome 位置、見つからなかったらNoneとなります。要素の位置を先頭から見つけるArray.tryFindIndexや、結果をoptionではなく実際の値で得られるArray.findIndexBackもあります。

Array.tryFindIndexBack
Array.tryFindIndexBack (fun n -> n % 2 = 1) [|1; 2; 3|]  // Some 2

Array.tryFindIndex     (fun n -> n % 2 = 1) [|1; 2; 3|]  // Some 0

Array.findIndexBack    (fun n -> n % 2 = 1) [|1; 2; 3|]  // 2

Array.tryHead 配列
'T [] -> 'T option

配列の先頭の要素を取り出します。要素が存在すればSome 要素、要素が存在しなければNoneとなります。結果をoptionではなく実際の値で得られるArray.headや、末尾の要素を得るArray.tryLastもあります。

Array.tryHead
(* 先頭の要素が存在するとき *)
Array.tryHead [|3; 1; 2|]  // Some 3
Array.head [|3; 1; 2|]  // 3

(* 先頭の要素が存在しないとき *)
Array.tryHead<int> [||]  // None
Array.head<int>    [||]  // 例外発生「System.ArgumentException: 入力配列が空でした。」

Array.tryLast [|3; 1; 2|]  // Some 2

Array.tryItem 位置 配列
int -> 'T [] -> 'T option

指定した位置の要素を取り出します。要素が存在すればSome 要素、存在しなければNoneとなります。結果がoptionではなく要素で得られるArray.itemもあります。

Array.tryItem
(* 指定した位置に要素が存在するとき *)
Array.tryItem 2 [|'c'; 'a'; 'b'|]  // Some 'b'
Array.item    2 [|'c'; 'a'; 'b'|]  // 'b'

(* 指定した位置に要素が存在しないとき *)
Array.tryItem 4 [|'c'; 'a'; 'b'|]  // None
Array.item    4 [|'c'; 'a'; 'b'|]  // 例外発生「System.IndexOutOfRangeException」

Array.tryLast 配列
'T [] -> 'T option

配列の末尾の要素が得られたらSome 要素、得られなければNoneとなります。
結果がoptionではなく要素自身となるArray.lastもありますが、こちらは配列が空だと例外が発生します。また、配列の先頭の要素を得られるArray.tryHeadもあります。

Array.tryLast
Array.tryLast [|3; 1; 2|]  // Some 2
Array.tryLast<int> [||]    // None

Array.last    [|3; 1; 2|]  // 2
Array.last<int> [||]       // 例外発生「System.ArgumentException: 入力配列が空でした。」

Array.tryHead [|3; 1; 2|]  // Some 3

Array.unfold 関数 初期値
('T -> ('U * 'T) option) -> 'T -> 'U []

初期値を元に関数を累積的に実行して列をつくります。関数の引数は初期値および前回の結果とし、戻り値は、次回も関数を実行するときはSome(結果となる配列の要素, 次回実行時の引数)、関数の実行を終了するときはNoneとします。

Array.unfold
Array.unfold (fun n -> if n > 5 then None else Some (n, n + 1)) 1
// [|1; 2; 3; 4; 5|]

(* フィボナッチ数列の配列(Array.unfold) *)
let fibs n = Array.unfold (fun (x, y, z) ->
             if z > 0 then Some (x, (y, x + y, z - 1)) else None)
             <| (1, 1, n)
// fibs 10 = [|1; 1; 2; 3; 5; 8; 13; 21; 34; 55|]

(* フィボナッチ数(Array.fold) *)
let fib n = fst <| Array.fold (fun (x, y) _ -> (x + y, x)) (0, 1) [|1..n|]
// fib 10 = 55

Array.where 関数 配列
('T -> bool) -> 'T [] -> 'T []

Array.filterと同様に、配列の各要素で実行した関数の結果がtrueとなるものをすべて取り出します。Array.findでは最初にtrueとなる要素のみとなるのが違います。

Array.where
Array.where  (fun n -> n % 2 = 0) [|1..5|]  // [|2; 4|]
Array.filter (fun n -> n % 2 = 0) [|1..5|]  // [|2; 4|]

Array.find   (fun n -> n % 2 = 0) [|1..5|]  // 2

Array.windowed 要素数 配列
int -> 'T [] -> 'T [] []

指定した要素数だけ位置が連続する配列を要素とするジャグ配列を得られます。要素数が正の整数でないときはSystem.ArgumentExceptionが発生します。また、要素数が配列の要素の数を上回ると結果の配列は空となります。

要素数を2に指定すると結果がArray.pairwiseと似てきますが、要素がタプルか配列かが違います。Array.chunkBySizeとの違いは、ただ配列の要素を区切るのではなく、先頭の要素から順次要素数だけ連続する要素を1つの配列にまとめているところです。

Array.windowed
Array.windowed 3 [|'a'..'e'|]  // [|[|'a'; 'b'; 'c'|]; [|'b'; 'c'; 'd'|]; [|'c'; 'd'; 'e'|]|]
Array.windowed 0 [|'a'..'e'|]  // 例外発生「System.ArgumentException: 入力は正である必要があります。」
Array.windowed 6 [|'a'..'e'|]  // [||] : char [] []

(* windowedとpairwiseとの違い *)
Array.windowed 2 [|'a'..'e'|]  // [|[|'a'; 'b'|]; [|'b'; 'c'|]; [|'c'; 'd'|]; [|'d'; 'e'|]|]
Array.pairwise   [|'a'..'e'|]  // [|('a', 'b'); ('b', 'c'); ('c', 'd'); ('d', 'e')|]

(* windowedとchunBySizeとの違い *)
Array.windowed    3 [|'a'..'e'|]  // [|[|'a'; 'b'; 'c'|]; [|'b'; 'c'; 'd'|]; [|'c'; 'd'; 'e'|]|]
Array.chunkBySize 3 [|'a'..'e'|]  // [|[|'a'; 'b'; 'c'|]; [|'d'; 'e'|]|]

Array.allPairs 配列1 配列2
'T [] -> 'U [] -> ('T * 'U) []

配列1と配列2の各要素のすべての組み合わせをタプルの要素とする配列を得られます。結果となる配列の長さが膨大になる可能性があるため、引数の配列の長さに注意してください。また、引数の配列のどちらかが空のときは結果の配列も空になります。

Array.allPairs
Array.allPairs   [|'a'; 'b'; 'c'|] [|1; 2|]  // [|('a', 1); ('a', 2); ('b', 1); ('b', 2); ('c', 1); ('c', 2)|]
Array.allPairs<char, int> [|'a'; 'b'|] [||]  // [||] : (char * int) []

ドキュメントが更新されたら、このページは不要になると思いますが、その時までご覧になった方々の参考になればと思います。

6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?