F#、C#、SQLで直積

Seq.collectやSelectManyが理解しづらいので簡単なコードで整理してみました。

F#

[<Test>]
let ``cartesian product`` () =
let numbers = seq {for i in 1 .. 3 -> i}
let results =
numbers
|> Seq.collect (fun n1 -> numbers |> Seq.map (fun n2 -> n1, n2))
results
|> Seq.iter (printfn "%A")

C#

[TestMethod]
public void TestCartesianProduct()
{
var numbers = Enumerable.Range(1, 3);
var results = numbers
.SelectMany(n1 => numbers.Select(n2 => Tuple.Create(n1, n2)));
results
.ToList()
.ForEach(Console.WriteLine);
}

C# (LINQ)

[TestMethod]
public void TestCartesianProduct_Linq()
{
var numbers = Enumerable.Range(1, 3);
var results =
from n1 in numbers
from n2 in numbers
select Tuple.Create(n1, n2);
results
.ToList()
.ForEach(Console.WriteLine);
}

SQL

SQL Server 2008を使っています。再帰クエリでつくった連番をテーブル型の変数に格納し、それから結合しています。

declare @numbers table (n int);with x (id) as (
select 1
union all
select id + 1 from x where id + 1 <= 3
)insert into @numbers select * from x;

select a.n n1, b.n n2 from @numbers a, @numbers b

出力結果

出力結果はいずれも1,2,3の集合の直積になります。

n1 n2
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3