スポンサーサイト

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

F#によるLinq to Obj入門 (8) Join

まずはサンプル用のレコード型とシークエンスを定義しておきます。
 
type Emp =
    {ID : int;//ID番号
     name : string;//名前
     height : float;//身長
     sex :int //0が男,1が女
     }
     member this.disp () =
        printfn "%2d %s %3.1f %A" this.ID this.name this.height this.sex
 
let EmpSeq = seq[{ID = 1;name = "Jhon";height = 168.3;sex = 0};
                {ID = 3;name = "Jhon";height = 161.1;sex = 0};
                {ID = 8;name = "Kim";height = 168.3;sex = 1};
                {ID = 2;name = "Sawyer";height = 168.7;sex = 0};
                {ID = 13;name = "Michael";height = 155.0;sex = 0};
                {ID = 19;name = "Revecca";height = 154.8;sex = 1};
                {ID = 11;name = "Hugo";height = 176.6;sex = 0};
                {ID = 21;name = "Maggie";height = 149.1;sex = 1};
                {ID = 7;name = "Ben";height = 157.6;sex = 0}]
 
今回ここに別のレコード型とシークエンスを追加します。
 
type Sex =
    { S_ID :int;
      expInJ : string
      expInE : string}
 
let SexSeq = seq[{S_ID = 0;expInJ = "男";expInE = "Man"};
                 {S_ID = 1;expInJ = "女";expInE = "Woman"}]  
 
ここまでで、リレーショナルデータベースでは、いわば二つの表定義とデータ入力が終わった状態に対応します。
Joinはこの二つの表をつなげるという作用です。
EmpのseqフィールドとSexのS_IDフィールドをキーとしてつないでみます。
 
Enumerableのstaticなメソッドとして次のような関数があります。
 
static member Join : 
        outer:IEnumerable<'TOuter> * 
        inner:IEnumerable<'TInner> * 
        outerKeySelector:Func<'TOuter, 'TKey> * 
        innerKeySelector:Func<'TInner, 'TKey> * 
        resultSelector:Func<'TOuter, 'TInner, 'TResult> -> IEnumerable<'TResult> 
 
最初のouterが結合させる第一シークエンス
次のinnerが結合させる第二シークエンス
次のouterKeySelectorが第一シークエンスの要素から結合の基準となるキーを抜き出す関数
次のinnerKeySelectorが第二シークエンスの要素から結合の基準となるキーを抜き出す関数
最後のresultSelectorがキーが一致したとき「それぞれの要素を用いてどのような要素を要素として新しいシークエンスを作るか」を指定する関数です。
 
使ってみます。
 
> let res1 = Enumerable.Join (EmpSeq,SexSeq,(fun oute -> oute.sex),(fun inn -> inn.S_ID),(fun oute inn -> (oute.name,inn.expInJ)) )
;;
 
val res1 : seq<string * string>
 
> Seq.iter (fun x -> printf "%A :" x) res1;;
("Jhon", "男") :("Jhon", "男") :("Kim", "女") :("Sawyer", "男") :("Michael", "男") :("Revecca", "女") :("Hugo", "男") :("Maggie", "女") :("Ben", "男") :val it : unit = ()
 
なお、Enumerable.Joinの第一引数のインスタンスメソッドとしても定義されていて次の様にも使えます。
 
> let res2 = EmpSeq.Join(SexSeq,(fun oute -> oute.sex),(fun inn -> inn.S_ID),(fun oute inn -> (oute.name,inn.expInJ)))
;;
 
val res2 : seq<string * string>
 
> Seq.iter (fun x -> printf "%A :" x) res2;;
("Jhon", "男") :("Jhon", "男") :("Kim", "女") :("Sawyer", "男") :("Michael", "男") :("Revecca", "女") :("Hugo", "男") :("Maggie", "女") :("Ben", "男") :val it : unit = ()
 
Joinを自分で定義してみます。
 
> let myJoin outer inner outerKeySelector innerKeySelector resultSelector =
    seq{ for outerEle in outer do
            for innerEle in inner do
                if (outerKeySelector outerEle) = (innerKeySelector innerEle) then
                    yield (resultSelector outerEle innerEle)};;
 
val myJoin :
  seq<'a> ->
    seq<'b> -> ('a -> 'c) -> ('b -> 'c) -> ('a -> 'b -> 'd) -> seq<'d>
    when 'c : equality
    
こう定義してみると、outerとかinnerの意味合いが分かりやすくなります。(外側のforループと内側のforループとの対応です。)
 
こちらも使ってみます。
 
> let res3 = myJoin EmpSeq SexSeq (fun oute -> oute.sex) (fun inn -> inn.S_ID) (fun oute inn -> (oute.name,inn.expInJ)) 
;;
 
val res3 : seq<string * string>
 
> Seq.iter (fun x -> printf "%A :" x) res3;;
("Jhon", "男") :("Jhon", "男") :("Kim", "女") :("Sawyer", "男") :("Michael", "男") :("Revecca", "女") :("Hugo", "男") :("Maggie", "女") :("Ben", "男") :val it : unit = ()
 
スポンサーサイト

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

プロフィール

T GYOUTEN

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

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

この人とブロともになる

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