スポンサーサイト

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

F#によるLinq to Obj入門 (9) SelectMany

今回はSelectManyの紹介です。
SelectはLINQ版のmapで、値を別の値に変換していく仕組みでした。
シークエンス1               シークエンス2
_______a1____------変換--------> b1
_______a2____------変換--------> b2
_______a3____------変換--------> b3
_______a4____------変換--------> b4
_______a5____------変換--------> b5
 
いわばこれは「1対1の対応」で、シークエンス1からシークエンス2を作り出す仕組みでしたが、
これに対してSelectManyは「1体多の対応」で,シークエンス1からシークエンス2を作り出す仕組みです。
 
シークエンス1               シークエンス2
_______a1____------変換--------> b11
_______________________--------> b12
_______________________--------> b13
_______a2____------変換--------> b21
_______________________--------> b22
_______________________--------> b23
_______a3____------変換--------> b31
_______________________--------> b32
_______________________--------> b33
 
一つ例をあげてみます。

 
> let res1 = Enumerable.SelectMany(seq[10;20;30],(fun x ->seq[x+1;x+2;x+3]));;
 
val res1 : seq<int>
 
> res1 |> Seq.iter (fun x -> printf "%A :" x) ;;
11 :12 :13 :21 :22 :23 :31 :32 :33 :val it : unit = ()
 
この場合関数が(fun x ->seq[x+1;x+2;x+3])で、xに対してx+1,x+2,x+3という3つの値をもつシークエンスを生成しています。
 
通常のSelectだと
> Enumerable.Select(seq[10;20;30],(fun x ->seq[x+1;x+2;x+3]));;
val it : seq<seq<int>> = seq [[11; 12; 13]; [21; 22; 23]; [31; 32; 33]]
 
となるのですが、SelectManyの場合は関数を施した、結果のシークエンスから一段階中身を取り出すという作業がプラスされています。
 
もう一つ例をやってみます。
 
> let res2 = Enumerable.SelectMany(seq["太郎";"一郎";"次郎"],(fun x ->seq[x+"くん";x+"さん"]));;
val res2 : seq<string>
 
> res2 |> Seq.iter (fun x -> printf "%A :" x) ;;
"太郎くん" :"太郎さん" :"一郎くん" :"一郎さん" :"次郎くん" :"次郎さん" :val it : unit = ()
 
シンタックスは次のようになっています。(この他にもオーバーロードされたものがあります)
 
static member SelectMany : 
        source:IEnumerable<'TSource> * 
        selector:Func<'TSource, IEnumerable<'TResult>> -> IEnumerable<'TResult> 
 
 
では自前でSelectManyを書いてみます。
 
> let mySelectMany1 source selector =
    seq{ for s in source do
            let temp = s |> selector 
            for t in temp do
                yield t};;
 
val mySelectMany1 : seq<'a> -> ('a -> #seq<'c>) -> seq<'c>
 
 
> let res3 = mySelectMany1 (seq[10;20;30]) (fun x ->seq[x+1;x+2;x+3]);;
val res3 : seq<int>
 
> res3 |> Seq.iter (fun x -> printf "%A :" x) ;;
11 :12 :13 :21 :22 :23 :31 :32 :33 :val it : unit = ()
 
いわば、SelectManyは「シークエンスの要素と作用の総当たり戦」という感じです。
 
なおLINQの他のメソッドと同様に、第一引数のインスタンスメソッドとしても使用できるので次の様にも書くことができます。
 
> seq[10;20;30].SelectMany (fun x ->seq[x+1;x+2;x+3]);;
val it : seq<int> = seq [11; 12; 13; 21; ...]
 
SeqモジュールでSelectManyに対応するのはSeq.collectで次のように使用します。
 
> Seq.collect (fun x ->seq[x+1;x+2;x+3]) (seq[10;20;30]);;
val it : seq<int> = seq [11; 12; 13; 21; ...]
 
スポンサーサイト

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

コメントの投稿

非公開コメント

プロフィール

T GYOUTEN

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

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

この人とブロともになる

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