2009-06-01 121 views
6

我是f新手#用F#計算笛卡爾乘積列表的乘積

我試着計算笛卡爾乘積的列表中的乘積。我「借」這個。

let xs = [1..99] 
let ys = [1..99] 
seq {for x in xs do for y in ys do yield x * y} 

有沒有更好或更優雅的方式?

加里

+0

相關問題在這裏:http://stackoverflow.com/questions/482866/f-cross-product-of-two-lists – Benjol 2009-06-02 06:56:56

回答

9

另一個possibiltiy基於列表模塊提供的是功能來解決這個問題:

let xs = [1..99] 
let ys = [1..99] 
let zs = xs |> List.collect (fun x -> ys |> List.map (fun y -> x*y)) 

避免了額外要求,以.concat,也應該做的工作。

但我會堅持你的解決方案。它應該是最可讀的,它是一個真正的匹配者。 (只是試着大聲地讀出代碼,你完全可以理解,而Noldorins或我的不是)

2

的確有一個稍微更優雅的方式(至少在功能意義上)來計算笛卡爾乘積,其使用存在於List類內的功能。 (有沒有必要讓序列或環這裏,至少不是直接)

試試這個:

let xs = [1..99] 
let ys = [1..99] 
xs |> List.map(fun x -> ys |> List.map(fun y -> x * y)) |> List.concat 

稍長無可否認,儘管功能更強大的風格,它似乎。

+1

其實在問題中的代碼比你的代碼更接近列表理解,在我看來。你的更像是一個列表理解的desugared版本。 – 2009-06-01 21:10:47

+0

是的,我並不是指列表解析實際上 - 我不確定它有一個特殊的名稱,但我的意思是List。*函數。 – Noldorin 2009-06-02 03:19:54

+0

您可以詳細說明「無需涉及序列」的含義嗎,我不明白在Seq.map上使用List.map會帶來哪些好處? – ninegrid 2009-06-02 21:40:01

7

聲明:我沒有安裝當前F#的機器,所以我無法測試我的代碼。基本上,不過,如果你從哈斯克爾偷sequence,你可以寫你的程序作爲

let cartesian = sequence >> List.map product 

,並運行它

cartesian [[1..99]; [1..99]] 

下面是如何寫sequence。這是你寫的序列表達式的一個通用版本。它只處理無限數量的列表:{ for x in xs do for y in ys do for z in zs ... yield [x;y;z;...] }

let rec sequence = function 
    | [] -> Seq.singleton [] 
    | (l::ls) -> seq { for x in l do for xs in sequence ls do yield (x::xs) } 
// also you'll need product to do the multiplication 
let product = Seq.fold_left1 (*) 

然後,你可以寫你的程序作爲

let cartesian xs ys = [xs; ys] |> sequence |> List.map product 
// ... or one-argument, point-free style: 
let cartesian' = sequence >> Seq.map product 

您可能需要改變一些Seq s到List秒。

但是,能夠猜出非一般列表理解含義的人數可能比識別名稱sequence多很多,所以你可能比列表理解更好。 sequence隨時可以運行整個計算表達式列表。