列表的笛卡尔半平方

时间:2015-04-28 15:51:05

标签: f# cartesian-product

如何在F#中生成列表的笛卡尔积的问题是一个熟悉的问题,但我需要稍微不同的东西:得到的正方形的一半。也就是说,[1; 2; 3] - > [(1,2),(1,3),(2,3)]。

最明显的方法是使用整数索引嵌套for循环,但在F#中最常用的方法是什么?我不关心性能,只关注简洁和优雅。

2 个答案:

答案 0 :(得分:4)

我不确定,但我认为你想要这样的事情:

let pairs = function
   | [] -> [] 
   | (x::xs) -> List.map (fun x' -> (x,x')) xs

let rec hSquare xs =                        
   match xs with                           
   | [] -> []                              
   | (_::ys) -> pairs xs @ hSquare ys

hSquare为例:

> hSquare [1..3];;
val it : (int * int) list = [(1, 2); (1, 3); (2, 3)]
> hSquare [1..4];;
val it : (int * int) list = [(1, 2); (1, 3); (1, 4); (2, 3); (2, 4); (3, 4)]

包含您的示例

备注

  • 这肯定不是通常的笛卡尔积的一半(在你的情况下是[(1,1);(1,2);(1,3);(2,1);(2,2);(2,3);(3,1);(3,2);(3,3)]
  • 我不关心性能,尾巴,无论如何 - 你一定能在这方面有所改进。
  • 我只是想知道你是否正在寻找这个,并且要发表评论。

答案 1 :(得分:1)

以下是基于Carsten König's exploratory answer的强制性替代方案:也可以使用Sequence Expression来实现这些结果。

let c2 args = seq{
    let argsi = Seq.mapi (fun i x -> i, x) args 
    for (i, x) in argsi do
        for (j, y) in argsi do
            if i < j then yield (x, y) }

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