スポンサーサイト

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

F#によるLinq to Obj入門 (5) Distinct Union等

今回はシークエンスを集合としてとらえたときの取り扱いです。 
 
Distinctは単一化を施します。 
なお、要素はequalityが定義されている必要があります。 
 
例 
 
> seq[3;1;2;3;2].Distinct();; 
val it : seq<int> = seq [3; 1; 2] 
 
Unionは1つシークエンスにもう一つのシークエンスを足します。(足すといっても、和集合を返すということです。) 
 
> seq[3;2;1;0;-1].Union(seq[0;9;1;8]) 
|> Seq.iter (fun x -> printf "%d " x) ;; 
3 2 1 0 -1 9 8 
 
Intersectは一つのシークエンスに対し、もう一つのシークエンスを引数として渡し、共通部分のシークエンスを返します。 
 
> seq[3;2;1;0;-1].Intersect(seq[0;9;1;8]) 
|> Seq.iter (fun x -> printf "%d " x) ;; 
1 0  
 
Exceptは一つのシークエンスseq1に対し、もう一つのシークエンスeq2を引数として渡し、seq1のうちseq2に含まれるものを除いたものを返します。(いわゆる差です。) 
 
> seq[3;2;1;0;-1].Except(seq[0;9;1;8]) 
|> Seq.iter (fun x -> printf "%d " x) ;; 
3 2 -1 
 
Containsは一つのシークエンスに対し、ある値が要素であるかどうかをbool値で返します。 
 
> seq[3;2;1;0;-1].Contains(3);; 
val it : bool = true 
 
> seq[3;2;1;0;-1].Contains(7);; 
val it : bool = false 
 
 F#でいうとexistsがこれの拡張版にあたります。
 
 > Seq.exists ;;
val it : (('a -> bool) -> seq<'a> -> bool) = <fun:clo@15-2> 
  
Seq.exists f seqA で、seqAの要素にfを適用していって、一つでもtrueを返すものがあれば、trueを返します。
 
 ということで
 > seq[3;2;1;0;-1].Contains(7);; 
val it : bool = false 
 は
 > Seq.exists (fun x -> x = 7) (seq[3;2;1;0;-1]);;
val it : bool = false
 
もしくは
 
> Seq.exists ((=) 7) (seq[3;2;1;0;-1]);;
val it : bool = false
 
と書けます。  
 
Distinct        <-> Seq.distinct 
Union           <-> 対応するものなし 
Intersect       <-> 対応するものなし 
Except          <-> 対応するものなし 
Contains        <-> Seq.existsで対応可 
 
なおSeqモジュールにはSeq.distinctByというものが定義されていて、これは「キーを指定する関数」と一緒に使うと、キーが同じものが2回目以降現れるとそれを取り除くという働きをします。 
 
例 
 
> Seq.distinctBy (fun x -> x % 3) (seq[1;3;4;5;6;0]);; 
val it : seq<int> = seq [1; 3; 5] 
 
> seq["Jhon";"Kim";"Hugo";"Maggie";"Ben"] 
|> Seq.distinctBy (fun s  -> s.Length) ;; 
val it : seq<string> = seq ["Jhon"; "Kim"; "Maggie"] 
 
F#で集合的取り扱いをするにはSetを用いるのが普通です。 
Setでは、重複した要素は取り除かれることと、ソートされることに留意しておいてください。 
(いわば自動distinct,sort機能付きです。)、 
 
> let s1 = Set.ofSeq(seq[3;2;1;0;-1]) 
let s2 = Set.ofSeq(seq[0;9;1;8]);; 
 
val s1 : Set<int> = set [-1; 0; 1; 2; 3] 
val s2 : Set<int> = set [0; 1; 8; 9] 
 
Unionに対応 
> s1 + s2;; 
val it : Set<int> = set [-1; 0; 1; 2; 3; 8; 9] 
 
Intersectに対応 
> Set.intersect s1  s2;; 
val it : Set<int> = set [0; 1] 
 
Exceptに対応 
> s1 - s2;; 
val it : Set<int> = set [-1; 2; 3] 
 
Containに対応 
 
> Set.contains 3 s1;; 
val it : bool = true  
 
なおSetについてはこちらをご覧ください。
スポンサーサイト

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

コメントの投稿

非公開コメント

余計なお世話シリーズ

>Seq.Distinct
Seq.distinct

>Contains <-> 対応するものなし
s.Contains(5)
は、
Seq.exists ((=) 5) s

Set のつくり方アラカルト
let s1 = Set.ofSeq(seq[3;2;1;0;-1])
let s1 = new Set<int>(seq[3;2;1;0;-1])
let s1 = Set<int>(seq[3;2;1;0;-1])
let s1 = Set<int>([3;2;1;0;-1])
let s1 = set [3;2;1;0;-1]

No title

コメントありがとうございます。本文を訂正させていただきました。

setについては

> set;;
val it : (seq<'a> -> Set<'a>) when 'a : comparison = <fun:clo@8-1>

> let test se =
Set(se);;

val test : seq<'a> -> Set<'a> when 'a : comparison

なので、

> set [3;2;1];;
val it : Set<int> = set [1; 2; 3]
> set (seq[3;2]);;
val it : Set<int> = set [2; 3]
> set (seq{yield 1});;
val it : Set<int> = set [1]
> Set (seq{yield 1});;
val it : Set<int> = set [1]
等が可能になるわけなのですね。

Re:

set については、1.9.6で見たところでは、単に、Set.of_seq を呼び出す様になってます。
コンストラクタについては、
new Set( シーケンス )
set.fsi:
type Set<'T> =

/// Create a set containing elements drawn from the given sequence.
new : elements:seq<'T> -> Set<'T>
となっていて、うまくやってくれます。
リストや配列は、もともとシーケンスが必要とされるところには、シーケンスとして渡されるので、
seq [ リストの並び ]
とかでは、seq は、省略できます。
seq { シーケンス式 }
の場合については、省略出来る場合がありますが、基本省略できません。
ついでに、
エンプティシーケンスの意味で
seq<int> { }
とは書けません。

No title

詳細までありがとうございます。やっぱりコードを見るのが一番ですね。
個人的にSetは、好みのcollection型でついつい使ってしまいます。
プロフィール

T GYOUTEN

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

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

この人とブロともになる

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