スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

F#入門基本編落穂拾い その46 List.collect

今回はList.collectを紹介します。
まずは型から
> List.collect ;;
val it : (('a -> 'b list) -> 'a list -> 'b list) //#1
 
'a型の要素から'b型のリストの写像と、'a型のリストseedLstを与えると、seedLstの各要素に写像を作用させて、それぞれの場合の結果のリストを繋げて、一つのリストにして返してくれます。
 

> List.collect (fun x -> [x;x+1;x+2]) [0;10;20];;
val it : int list = [0; 1; 2; 10; 11; 12; 20; 21; 22]
 
これは「xから[x;x+1;x+2]という3つの要素をもつリストを作り出す関数」を0,10,20それぞれに作用させて、その結果の[0;1;2],[10,11,12],[20,21,22]を繋げて一つのリストにして返してくれています。
普通のmapでは、次のようになるところです。
 
> List.map (fun x -> [x;x+1;x+2]) [0;10;20];;
val it : int list list = [[0; 1; 2]; [10; 11; 12]; [20; 21; 22]]
 
ここで#1で'bを'aとしてみます。
(('a -> 'a list) -> 'a list -> 'a list) //#2
#2は非常に扱いやすい形で、('a  ->'a list)の形の関数をList.collect に部分適用すれば、これは
'a list -> 'a list 型の関数になるので、繰り返し適用していけます。
 

 
> let g1 = List.collect (fun x -> [x;2*x])
let g2=  List.collect (fun x -> [x+1;x+2;x+3])
let g3 = List.collect (fun x -> [3*x;3*x+1]);;
 
val g1 : (int list -> int list)
val g2 : (int list -> int list)
val g3 : (int list -> int list)
 
> [1] |> g1 |> g2 |> g3;;
val it : int list = [6; 7; 9; 10; 12; 13; 9; 10; 12; 13; 15; 16]
 
樹形図のようなものをイメージしてもらうと分かりやすいかもしれません。
 
1___1___2___6
____________7
________3___9
____________10
________4___12
____________13
____2___3___9
____________10
________4___12
____________13
________5___15
____________16
 
それではList.collectを利用して「文字列を総当たりで連結する関数」を定義してみます。
次のような動きをする関数です。
 
> connString [["A";"B";"C"];["1";"2"];["&";"$"]] ;;
val it : string list =
  ["A1&"; "A1$"; "A2&"; "A2$"; "B1&"; "B1$"; "B2&"; "B2$"; "C1&"; "C1$"; "C2&";
   "C2$"]
 
定義は次になります。
 
> let connString baseList =
        
    let addStr (a:string) (b:string) = a + b
    let f (v:string list) = (fun (k:string) -> List.map (addStr k) v)
       
    List.reduce (fun (s:string list) (x:string list) ->
                    let g = f s
                    x |> List.collect g )
                (List.rev baseList);;
 
val connString : string list list -> string list
 
使用例
 
> connString [["img"];["1";"2";"3"];["."];["1";"2";"3";"4";"5";"6"]];;
val it : string list =
  ["img1.1"; "img1.2"; "img1.3"; "img1.4"; "img1.5"; "img1.6"; "img2.1";
   "img2.2"; "img2.3"; "img2.4"; "img2.5"; "img2.6"; "img3.1"; "img3.2";
   "img3.3"; "img3.4"; "img3.5"; "img3.6"]
   
では同様に「リストを総当たりで連結する関数」を書いてみます。
 
> let connList (baseList :list<list<list<'a>>>) =
   
   let add2 (a:list<'a>) (l:list<'a>) = a @ l
   let f (v:list<list<'a>>) = (fun (k:list<'a>) -> (List.map (add2 k) v)) 
       
   List.reduce (fun (s:list<list<'a>>) (x:list<list<'a>>) ->
                    let g = f s
                    x |> List.collect g )
                (List.rev baseList);;
 
val connList : 'a list list list -> 'a list list
 
使用例
 
> connList [[["a"];["b"]];[["c"];["d"]]];;
val it : string list list = [["a"; "c"]; ["a"; "d"]; ["b"; "c"]; ["b"; "d"]]
 
> connList [[["a";"x"];["b"]];[["c"];["d"]]];;
val it : string list list =
  [["a"; "x"; "c"]; ["a"; "x"; "d"]; ["b"; "c"]; ["b"; "d"]]
スポンサーサイト

テーマ : プログラミング
ジャンル : コンピュータ

コメントの投稿

非公開コメント

プロフィール

T GYOUTEN

Author:T GYOUTEN
F#と英単語とフリーソフトと読書に興味があります。
ホームページでフリーソフトも公開しています。どぞ御贔屓に。

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
フリーエリア
フリーエリア
blogram投票ボタン
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QRコード
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。