スポンサーサイト

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

F#によるLinq to Obj入門 (18) クエリ式(参考)

C#ではクエリ式なるものが使えて

var nums = Enumerable.Range(1, 10);
var q = from n in nums       
        where n % 3 == 1     
        foreach (var n in q) 
     Console.WriteLine(n);

などという処理が可能です。(2行目から4行目がクエリ式です。)
(実際にはコンパイル時にクエリ式は、拡張メソッド形式に変換されたうえでコンパイルされます。)
クエリ式についてはGushwellさんの『C#プログラミングレッスン』のLINQ to Object部分がとても参考になります。

http://gushwell.ifdef.jp/magArchive.html

せっかくですから、ソリューションの中にC#とF#のプロジェクトを混在させて、クエリ式関連だけC#のコードとして書いて、他の部分をF#で書いてみます。

ソリューションに3つのプロジェクトを作成します。
(1)F#のプロジェクトData1
内部にファイルEmpData.fsでその内容は次の通り

module EmpData

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"}
                 ] 

(2)C#のプロジェクトLinqData
上のプロジェクトData1を参照設定しておく。
内部にファイルLinqData.cx  でその内容は次の通り

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LinqData
{
   public class MyQuery01c
    {
        public static IEnumerable<int> MyQuery01 (IEnumerable<int> arg) {

            var q = from p in arg
                    where p % 3 == 0
                    select 2*p;
            return q;
        }
    }

    public class MyQuery02c
    {
        public static IEnumerable<EmpData.Emp> MyQuery02(IEnumerable<EmpData.Emp> arg)
        {
            var q = from p in arg
                    where p.height >160.5
                    select p;
            return q;
        }
    }
   

(3)F#のプロジェクトLinqBlog2Main
上のプロジェクトData1とLinqDataを参照設定しておく。
内部にファイルmainLinq.fs
なお上の二つのプロジェクトをビルドしておく。(これでインテリセンスが使える)

open System

open System.Collections.Generic
open System.Collections
open System.Linq

let nums = seq[1;2;3;4;5;6;7]

nums
 |> LinqData.MyQuery01c.MyQuery01
 |> Seq.iter(fun x -> printfn "%d " x)
 
printfn ("-----------------------------")
 
EmpData.EmpSeq
 |> LinqData.MyQuery02c.MyQuery02
 |> Seq.map(fun p -> p.name)
 |> Seq.iter(fun x -> printfn "%s " x)

これでコンパイル実行すると次のように表示されます。

6
12
-----------------------------
Jhon
Jhon
Kim
Sawyer
Hugo
続行するには何かキーを押してください . . .

次にクエリとしてjoinを使ったものを使用してみます。
C#だけで使用する場合は匿名クラスが使えて便利なのですが、F#側から使うためには
クエリ結果格納用のクラスを作るか、タプルを利用する等の方法が必要となります。

○クエリ結果格納用のクラスを作る例

EmpData.fsの追加分

type Query3ResType(in_ID:int,in_name:string,in_sex:string) =
    member this.ID = in_ID
    member this.name = in_name
    member this.sex  = in_sex
   
-------------------------------------------------------------------
LinqData.csの追加分

public class MyQuery03c
{
        public static IEnumerable<EmpData.Query3ResType> MyQuery03(IEnumerable<EmpData.Emp> arg1, IEnumerable<EmpData.Sex> arg2)
        {
            var q = from emp in arg1
                    join sex in arg2 on emp.sex equals sex.S_ID
                    select new EmpData.Query3ResType(emp.ID, emp.name, sex.expInJ);
            return q;
        }
    }

-------------------------------------------------------------------
mainLinq.fsの追加分

LinqData.MyQuery03c.MyQuery03(EmpData.EmpSeq,EmpData.SexSeq)
 |> Seq.iter(fun x -> printfn "%2d:%s : %s" x.ID x.name x.sex)
 
-------------------------------------------------------------------
実行結果の一部

 1:Jhon : 男
 3:Jhon : 男
 8:Kim : 女
 2:Sawyer : 男
13:Michael : 男
19:Revecca : 女
11:Hugo : 男
21:Maggie : 女
 7:Ben : 男
続行するには何かキーを押してください . . .

○タプルを使用する場合

LinqData.csの追加分

    public class MyQuery04c
    {
        public static IEnumerable<Tuple<int, string, string>> MyQuery04(IEnumerable<EmpData.Emp> arg1, IEnumerable<EmpData.Sex> arg2)
        {
            var q = from emp in arg1
                    join sex in arg2 on emp.sex equals sex.S_ID
                    select new Tuple<int,string,string>(emp.ID, emp.name, sex.expInJ);
            return q;
        }
    }
   
-------------------------------------------------------------------
mainLinq.fsの追加分

LinqData.MyQuery04c.MyQuery04(EmpData.EmpSeq,EmpData.SexSeq)
 |> Seq.iter(fun (x,y,z) -> printfn "%2d:%s : %s" x y z)
 

-------------------------------------------------------------------
実行結果の一部

 1:Jhon : 男
 3:Jhon : 男
 8:Kim : 女
 2:Sawyer : 男
13:Michael : 男
19:Revecca : 女
11:Hugo : 男
21:Maggie : 女
 7:Ben : 男
続行するには何かキーを押してください . . .

ということで、いくぶん手間がかかるのですが、とりあえずクエリ式をC#で書いて、それをF#側から利用する方法の紹介でした。
とりあえずこれで「F#によるLinq to Obj入門」はおしまいです。
あと終わってないシリーズの続きとか並行処理についてのシリーズをやってみたいと思ってます。
知っていることを書くのでなく、勉強したことをまとめてみるというブログなので、不手際は多いのですが、ぼちぼち続けていきたいと思ってます。

スポンサーサイト

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

コメントの投稿

非公開コメント

プロフィール

T GYOUTEN

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

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

この人とブロともになる

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