列表的笛卡尔半方
Cartesian half-square of a list
如何在 F# 中生成列表与自身的笛卡尔积的问题很常见,但我需要一些稍微不同的东西:结果平方的 half。也就是说,[1; 2; 3] -> [(1, 2), (1, 3), (2, 3)].
最明显的实现方式涉及带有整数索引的嵌套 for 循环,但在 F# 中最惯用的实现方式是什么?我不关心性能,只关心简单和优雅。
我不确定,但我想你想要这样的东西:
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)]
- 我不关心性能、tailcalls 等等 - 你肯定可以改进这一点。
- 我只是想知道您是否正在寻找这个并且它的评论太大了。
这是实现这些结果的基于 : one may also use a 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)]
如何在 F# 中生成列表与自身的笛卡尔积的问题很常见,但我需要一些稍微不同的东西:结果平方的 half。也就是说,[1; 2; 3] -> [(1, 2), (1, 3), (2, 3)].
最明显的实现方式涉及带有整数索引的嵌套 for 循环,但在 F# 中最惯用的实现方式是什么?我不关心性能,只关心简单和优雅。
我不确定,但我想你想要这样的东西:
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)]
- 我不关心性能、tailcalls 等等 - 你肯定可以改进这一点。
- 我只是想知道您是否正在寻找这个并且它的评论太大了。
这是实现这些结果的基于
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)]