2016-10-10 16 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)] 

這就是說,它並不完全解決您的問題,因爲它僅接受其輸入兩個列表,但延長它應該不會太困難。