2014-03-12 22 views
13

我是F#和函數式編程的新手。給定一個場景,你想迭代一個序列或字符串列表,並將其映射到一個不同類型的新列表,使用累加器,什麼是正確的功能方法?我可以在F#中使用可變變量來實現這一點,但我正在努力尋找正確的函數來使用它。這與我認爲的地圖很相似,但有國家的概念。F# - 使用累加器映射列表

換句話說,我想將字符串列表轉換爲win窗體單選按鈕列表,但是對於每個新按鈕,我想將20添加到前一個y座標。喜歡的東西:

new RadioButton(Text=str,Location=new Point(20,y+20),Width=350) 

回答

15

您可以使用List.fold Y:

open System.Drawing 
open System.Windows.Forms 

let getButtons() = 
    let strings = ["a"; "b"; "c"] 
    let (_, pointsRev) = List.fold (fun (offset, l) s -> (offset+20, (new RadioButton(Text=s, Location = new Point(20, offset), Width = 350))::l)) (0, []) strings 
    pointsRev |> List.rev 

的狀態包含當前一對偏移和當前輸出列表。輸出列表是以相反的順序構建的,因此必須在最後反轉。

您還可以使用Seq.map2:

let points = Seq.map2 (fun offset s -> new RadioButton(Text=s, Location = new Point(20, offset)) (Seq.initInfinite ((*)20)) strings |> List.ofSeq 
+0

不錯。開始時對於像我這樣的新手來說彎曲(語法仍然令人困惑),但我明白了。 – user3410575

+0

@Lee謝謝,這對我有很大幫助,但僅僅爲了您的信息,'List.fold'示例當前不會編譯(即使聲明瞭「strings」列表)。你可以編輯嗎? –

+0

@MarkBell - 查看更新。 – Lee

3

您可以訪問,並通過引用改變變量都

let x = ref 0 
x := !x + 5 
new Point(20,!x+20) 

,你可以使用這樣的變量內倒閉。

您也可以使用mapihttp://msdn.microsoft.com/en-us/library/ee353425.aspx

並增加其價值基於inew Point(20,i*20+20)

+0

啊我沒有看到MAPI,謝謝。關於ref方法,這仍然不是一種常用的「功能」方法,對嗎?我試圖強迫自己在學習過程中避免舊習慣。 – user3410575

+0

正確。但我個人仍然喜歡我的舊習慣。 – Cynede

1

使用List.fold是一個好主意(見接受的答案)。作爲一名F#初學者,我自己將摺疊分成了一個單獨的函數,並重命名了一些變量,以便我可以更清楚地理解事物。這似乎工作:

let buttonNames = ["Button1Name"; "Button2Name"] 

let createRadioButton (offset, radioButtons) name = 
    let newRadioButton = new RadioButton(Text=name, Location=new Point(20, offset), Width=350) 
    (offset + 20, newRadioButton::radioButtons) 

let (_, buttonsReversed) = buttonNames |> List.fold createRadioButton (0, []) 

let buttons = buttonsReversed |> List.rev