スポンサーサイト

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

F#入門第50回(seq (3))

今回のお題は「seq (3)」です
 
今回はseq絡みの関数をいくつか紹介したいとおもいます。
 
まずはSeq.cacheからです。次をみてください。
 
> let fiboSeq =
    let rec nextFibo (n1,n2) =
       seq{ printf "*"
            yield n1+n2
            yield! nextFibo(n2,n1+n2)} 
    nextFibo(0,1) ;;         
 
val fibo : seq<int>
    
これはフィボナッチ数列を与えているのですが、最初のいくつかの項を取ってきてみます。
まずは一つだけ。


> Seq.take 1 fiboSeq;;
*val it : seq<int> = seq [1]
 
ここで*がyield n1+n2が実行された回数です。 
 
次に二つ。

> Seq.take 2 fiboSeq;;
**val it : seq<int> = seq [1; 2]
 
これらからわかるのは、毎回最初から計算しなおしているということです。
ここでSeq.cacheを利用すると、計算しているものを記録しておいて、残りの必要分だけ計算して返してくれます。
次のようにします。
 
> let fiboSeq =
    let rec nextFibo (n1,n2) =
       seq{ printf "*"
            yield n1+n2
            yield! nextFibo(n2,n1+n2)} |> Seq.cache
    nextFibo(0,1)  ;;
 
val fiboSeq : seq<int>
 
実行例
> Seq.take 1 fiboSeq;;
*val it : seq<int> = seq [1]
 
> Seq.take 2 fiboSeq;;
*val it : seq<int> = seq [1; 2] //計算回数が減っている
 
次に、SeqにはSeq.groupBy等のSQLチックな関数を紹介します。
 
まずサンプル例のためrecord型を二つとそれぞれのsequenceを定義しておきます。
 
type People =
    { p_index:int;
      name:string;
      height:float;
      pref_index :int}
                 
type Prefecture =
    {index : int;
     name: string}
     
let peoples = seq[ {p_index = 1;name = "John";height = 172.0;pref_index = 3};
                   {p_index = 2;name = "Ben";height = 192.0;pref_index = 1};
                   {p_index = 3;name = "Tom";height = 151.0;pref_index = 1};
                   {p_index = 4;name = "Paul";height = 174.0;pref_index = 2};
                   {p_index = 5;name = "Kate";height = 163.0;pref_index = 3}]
                       
let prefectures = seq[{index = 1;name = "Aomori"};
                      {index = 2;name = "Iwate"}; 
                      {index = 3;name = "Saga"}] 
                      
まずはSeq.sortByを使って並べ替えてみます。
 
let q = peoples 
        |> Seq.sortBy (fun p -> p.height)
 
表示用部分だけ文字列として抜き出します。
 
let q = peoples 
        |> Seq.sortBy (fun p -> p.height)
        |> Seq.map (fun p -> sprintf "name = %s height = %f" p.name p.height)
        
実行例
 
> q;;
val it : seq<string> =
  seq
    ["name = Tom height = 151.000000"; "name = Kate height = 163.000000";
     "name = John height = 172.000000"; "name = Paul height = 174.000000"; ...]
 
次にgruopByを使ってみます
 
let q = peoples 
        |> Seq.groupBy (fun p -> p.pref_index)
 
 
q;;
val it : seq<int * seq<People>> =
  seq
    [(3, seq [{p_index = 1;
               name = "John";
               height = 172.0;
               pref_index = 3;}; 
               {p_index = 5;
                name = "Kate";
                height = 163.0;
                pref_index = 3;}]);
     (1, seq [{p_index = 2;
               name = "Ben";
               height = 192.0;
               pref_index = 1;};
               {p_index = 3;
                name = "Tom";
                height = 151.0;
                pref_index = 1;}]);
     (2, seq [{p_index = 4;
               name = "Paul";
               height = 174.0;
               pref_index = 2;}])]
 
ちょっと複雑になりますが、pref_index毎のheightの和を求めてみます。
 
let u = peoples 
        |> Seq.groupBy (fun p -> p.pref_index)
        |> Seq.map (fun (index,sequ) -> sprintf "%d : %f" index (Seq.sumBy(fun p2 -> p2.height) sequ) )
        
> u;;
val it : seq<string> =
  seq ["3 : 335.000000"; "1 : 343.000000"; "2 : 174.000000"]
  
次にpeoplesとprefecturesをpeoplesのpref_indexとprefecturesのindexをキーとして結び付けてみたいとおもいます。
 

let u = seq{for p in peoples do
                for pre in prefectures do
                    if p.pref_index = pre.index then
                        yield sprintf "%s is from %s" p.name pre.name }
                        
                        
実行例
> u;;
val it : seq<string> =
  seq
    ["John is from Saga"; "Ben is from Aomori"; "Tom is from Aomori";
     "Paul is from Iwate"; ...] 
     

スポンサーサイト

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

コメントの投稿

非公開コメント

No title

>最初の3つを取ってきてみます
意味不明

No title

またまたすいません。訂正しました。
プロフィール

T GYOUTEN

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

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

この人とブロともになる

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