2016-10-10 38 views
3

我想要一个函数f,它获取列表并返回从每个列表中取一个元素所产生的所有可能组合的元组列表。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)] 

我正在考虑滚动我自己的,但感觉像那里必须是一个库函数比我的拇指拳头方法更好地优化,但我似乎无法找到任何搜索(我可能不知道这个正确的组合术语,所以继续打不同的组合方法&函数)

回答

6

就像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")] 
3

F#标准库中没有实现“笛卡尔乘积”。创建你自己的实现(例如使用列表解析)非常好。

1

其实,CaringDev和马克塞曼是不完全正确。目前还没有库实现,但在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)] 

这就是说,它并不完全解决您的问题,因为它仅接受其输入两个列表,但延长它应该不会太困难。