2017-12-17 22 views
3

私は2つの順序付けられたキーと値のペアを持っていて、値のペアを生成するために内部equi-joinを実行する必要があります:seq<'a * 'b> -> seq<'a * 'c> -> seq<'b * 'c>クエリの外でjoin-likeの関数関係演算子

これは、拡張メソッドSystem.Linq.Enumerableに簡単に配線することができます。

let foo abs acs = 
    System.Linq.Enumerable.Join(abs, acs, 
     (fun ab -> fst ab), (fun ac -> fst ac), 
     fun ab ac -> snd ab, snd ac) 
foo ["A",1;"B",2] ["B",1;"C",2;"B",3] 
// val it : System.Collections.Generic.IEnumerable<int * int> = 
// seq [(2, 1); (2, 3)] 

その機能をF#に変換するのはそれほど簡単ではありません。デカルト製品でのフィルタリングを避けるために、私はおそらく、必要に応じていくつかの怠惰/実行を失っているでしょう。

let bar abs acs = 
    let d = dict(Seq.groupBy fst acs) in seq{ 
     for a, b in abs do 
      let ok, cs = d.TryGetValue a 
      if ok then for c in cs -> b, snd c } 
bar ["A",1;"B",2] ["B",1;"C",2;"B",3] 
// val it : seq<int * int> = seq [(2, 1); (2, 3)] 

しかし、特定のサブ問題に対する手作りの、別注の解決策のように、それは非常に重いと感じます。 relational operatorsに、もっと一般的な、抽象的なやり方で、自然、半、反外、または外部結合にもどうやってアプローチできますか?

+2

'System.Linq.Enumerable'を使用して何が問題になっていますか? – mydogisbox

+1

F# 'Seq'モジュールは' Enumerable.Join'でハッシュ結合を提供しません。何か問題がなければ、LINQバージョンを使用してください。 –

+1

また、クエリ式を使用することもできます。https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/query-expressions – mydogisbox

答えて

3

query expressionを使用して同じことを達成できます。

query { 
    for a in ["A",1;"B",2] do 
    join b in ["B",1;"C",2;"B",3] on (fst a = fst b) 
    select (snd a, snd b) };; 

val it : seq<int * int> = seq [(2, 1); (2, 3)] 

また、ちょうどSystem.Linq.Enumerable.Joinを使うことには何も問題はありません。