F#中是否有库函数组合来自不同列表的元素

时间:2016-10-10 16:27:48

标签: f# combinatorics

我想要一个函数f,它接受​​一个列表列表,并返回通过从每个列表中取一个元素而产生的所有可能组合的元组列表。

例如

f [["A";"B";"C"];[1;2]]

会给出结果:

[("A",1);("A",2);("B",1);("B",2);("C",1);("C",2)]

f [[onions;peas];[mash;fries];[chicken;steak]]

会给:

[(onions,mash,chicken);(onions,mash,steak);(onions;fries;chicken) ... (peas,fries,steak)]

我正在考虑自己滚动,但觉得必须有一个库函数比我的拇指拳法更好地优化但我似乎无法通过谷歌搜索找到任何东西(我可能不知道正确的组合术语,所以保持达到不同的组合方法和功能)

3 个答案:

答案 0 :(得分:7)

与CaringDev一样,我不认为有任何标准的库函数可以做到这一点。我认为其中一个原因是它们会有不同的类型。

来自OP的[["A";"B";"C"];[1;2]]等代码甚至无法编译,因为字符串值的使用向编译器指示这是一个嵌套的字符串列表,但[1;2]是一个列表整数。

可以用元组代替,但这是一对的组合函数与三元组的组合函数不同,依此类推。

尽管如此,这些功能实现起来微不足道:

let combine2 xs ys = [
    for x in xs do
    for y in ys do
    yield x, y ]

let combine3 xs ys zs = [
    for x in xs do
    for y in ys do
    for z in zs do
    yield x, y, z ]

示例:

> combine2 ["A";"B";"C"] [1;2];;
val it : (string * int) list =
  [("A", 1); ("A", 2); ("B", 1); ("B", 2); ("C", 1); ("C", 2)]
> combine3 ["onions"; "peas"] ["mash"; "fries"] ["chicken"; "steak"];;
val it : (string * string * string) list =
  [("onions", "mash", "chicken"); ("onions", "mash", "steak");
   ("onions", "fries", "chicken"); ("onions", "fries", "steak");
   ("peas", "mash", "chicken"); ("peas", "mash", "steak");
   ("peas", "fries", "chicken"); ("peas", "fries", "steak")]

答案 1 :(得分:3)

没有实施笛卡尔产品"在F#标准库中。创建自己的实现(例如使用列表推导)非常好。

答案 2 :(得分:2)

实际上,CaringDev和Mark Seemann并不完全正确。目前还没有库实现,但F#4.1(即将推出TM )中将有一个笛卡尔积产品实现:https://github.com/Microsoft/visualfsharp/pull/989。它可以像这样使用:

List.allPairs ["A"; "B"; "C"] [1; 2]
//val it : (string * int) list =
//[("A", 1); ("A", 2); ("B", 1); ("B", 2); ("C", 1); ("C", 2)]

也就是说,它并没有完全解决你的问题,因为它只接受两个输入列表,但扩展它应该不会太困难。