笛卡尔积两个列表

时间:2012-02-09 15:31:06

标签: f# f#-interactive f#-scripting

  

可能重复:
  F# - cross product of two lists
  Projecting a list of lists efficiently in F#

我有一个带有两个整数列表的函数,并返回一个包含所有笛卡尔积的列表。我认为我有正确的想法,但没有正确的实施。我可以得到一些指示吗?

let rec cartesian = function
 | ([],[]) -> []
 | (xs,[]) -> []
 | ([],ys) -> []
 | (x::xs,ys) ->   List.map(fun y -> (x,y)::[]) cartesian (xs,ys) 

1 个答案:

答案 0 :(得分:10)

这是一个快速修复:

let rec cartesian = function
 | ([],[]) -> []
 | (xs,[]) -> []
 | ([],ys) -> []
 | (x::xs, ys) -> (List.map(fun y -> x,y) ys) @ (cartesian (xs,ys))

我们的想法是,对于每个元素x,您生成一个列表[(x, y1); (x, y2); ...; (x, yn)]并将这些列表连接起来。

在您的函数中,第一个模式匹配情况是多余的。并且参数更加便于以咖喱形式存在。该功能可能如下所示:

let rec cartesian xs ys = 
  match xs, ys with
  | _, [] -> []
  | [], _ -> []
  | x::xs', _ -> (List.map (fun y -> x, y) ys) @ (cartesian xs' ys)

一旦理解了这个想法,就会发现高阶函数List.collect与任务完全匹配:

let cartesian xs ys = 
    xs |> List.collect (fun x -> ys |> List.map (fun y -> x, y))