スポンサーサイト

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

F#によるLinq to Obj入門 (1) Select

LINQ to ObjectとはIEnumerable<'a>型(F#ではseq<'a>)のcollection(seq,list,array等)に対する一連の操作を与える仕組みです。seqをシークエンスとも呼ぶことにします。
 
とりあえず使うため次のようにしておきます。
 
>open open System 
open System.Collections.Generic
open System.Linq;;
 
ひとつseq型の値を定義します。
 
let t0 = [1;2;3]
 
これでt0. と打つと、いろいろ候補が現れるのでSelectを選んで次の様にします。
 
t0.Select(fun x -> 10*x)
let res0 = t0.Select(fun x -> 10*x)
 
まとめてfsiに送ると
 
val t0 : int list = [1; 2; 3]
val res0 : seq<int>
となり
 
> res0;;
val it : seq<int> = seq [10; 20; 30]
 
となります。
 
Selectメソッドは、拡張メソッドで、IEnumerable<'a>インターフェースに対し
て拡張されたものです。
 
見るからにmapと似ていますが,いわばSelectはmapのLinqでの別表現のようなものになっています。
 
> Seq.map (fun x -> 10*x) t0;;
val it : seq<int> = seq [10; 20; 30]
 
では
 
> t0 |> Seq.map (fun x -> 10 * x)
   |> Seq.map (fun x -> x + 2);;
val it : seq<int> = seq [12; 22; 32]
 
のLinqでの表現はどのようになるのでしょうか
正解は次です。
 
> t0.Select(fun x -> 10*x).Select(fun x -> x + 2);;
val it : seq<int> = seq [12; 22; 32]
 
つまりドットで次々につないでいく形式となります。
 
もちろんt0.Select(fun x -> 10*x)の結果がIEnumerableだから、できることです。
 
拡張メソッドのSelectは最終的にEnumerableクラスの静的メソッドのSelectメソッドの呼び出しに変換されます。Enumerable.Selectの第一引数はIEnuenrable<'a>(seq<'a>)型の値、第二引数はFunc<('a,'b >型となります。
すなわち
 
t0.Select(fun x -> 10*x)
 

 
Enumerable.Select (t0,(fun x -> 10*x))
 
とかくこともできます。(関数はFunc型に自動変換してくれます。)
 
> Enumerable.Select (t0,(fun x -> 10*x));;
val it : seq<int> = seq [10; 20; 30]
 
 
このことを利用して次のように定義するとLinqの関数を次の様にF#ライクに使えます。
 
> let select f s = Enumerable.Select(s,new Func<_,_>(f));;
 
val select : ('a -> 'b) -> seq<'a> -> seq<'b>
 
(注意)new Func<_,_>(f)でF#の関数fからFunc<_,_>デリゲートを生成してます。
 
使ってみます。
 
> t0 |> select (fun x -> 10*x);;
val it : seq<int> = seq [10; 20; 30]
 
> t0 |> select (fun x -> 10*x)
   |> select (fun x -> x+2);;
val it : seq<int> = seq [12; 22; 32]
 
(注)
C#では、さらに別のクエリ式というSQLに似た構文で書き換えることが可能です。
例えば上は
 
var res =from s in t0
            select (10*s);
 
と書き換えることができます。
 
F#では、これができないので、ドットで次々につないでいく拡張メソッド形式のみの紹介となります。
 
(おまけ)
 
var res =from s in t0
            select (10*s);
 
はF#でいうと
 
let res = seq{for s in t0 do
                yield (10*s)}
 
が一番近い表現かと思われます。
スポンサーサイト

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

コメントの投稿

非公開コメント

プロフィール

T GYOUTEN

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

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

この人とブロともになる

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