使用for循环在F#中向Map添加元素

时间:2014-04-14 08:02:00

标签: loops for-loop map f# add

代码:

let studentMap =
    for i = 0 to count do
        Map.empty.Add(students.[i].getId(), students.[i].getScores())

我正在尝试按顺序添加到地图中。我有一个数组中的学生对象,我正在尝试按顺序添加它们。我很困惑如何做到这一点。我想也许你制作一张空地图,然后按顺序通过for循环添加到它,但它总是会造成麻烦并且不会起作用。有没有办法使用for循环将项添加到地图? <key/value>对是:<string, int array>。这是我希望它格式化的方式,但它一直给我带来麻烦。我将再次重申目标以澄清:我希望能够使用for循环将项添加到地图中,我的学生对象数组用于获取我需要的相应数据。我将能够给它一个字符串并取回该学生的成绩。我知道这是一个我正在研究的奇怪问题,但我最初需要尝试一些简单的事情。

4 个答案:

答案 0 :(得分:7)

您可以尝试更实用的惯用法:

假设你有一个Student类型的数组(在下面的例子中是一个空数组):

let students = Array.empty<Student>

您可以将数组转换为Map

let mapStudents = students 
                    |> Array.map (fun s -> (s.getId(), s.getScore()))
                    |> Map.ofArray

答案 1 :(得分:2)

我认为Map.ofArray方法可能是最好的,但值得指出for循环可以做得更好:

let map = new System.Collections.Generic.Dictionary<int, Scores>()
for student in students do
   map.Add(student.getId(), student.getScore())

这巧妙地避免了数组绑定错误。

答案 2 :(得分:1)

你可以使用一个可变的地图变量:

let studentMap = 
    let mutable m <- Map.empty  
    for i = 0 to count do  
        m <- m.Add(students.[i].getId(), students.[i].getScores())
    m

或可变字典:

let studentMap = 
    let m = new System.Collections.Generic.Dictionary<int, Scores>()  
    for i = 0 to count do  
        m.Add(students.[i].getId(), students.[i].getScores())
    m

更实用的解决方案是使用折叠:

let studentMap = seq { 0 .. count } |> Seq.fold (fun (m: Map<int, Scores>) i -> m.Add(students.[i].getId(), students.[i].getScores())) Map.empty

答案 3 :(得分:0)

在函数式语言中,内置数据结构是不可变,也就是说,当你添加一个元素时,会返回一个新的数据结构值。

如果要将一个结构转换为另一个结构,通常可以使用其中一个内置函数,如Map.ofArray。如果您有一个更复杂的场景,比如生成值的函数,那么您可以使用'loop',并且循环的每次迭代都会返回数据结构的新值。以功能方式表达这种“循环”的方法是使用递归函数

let studentMap =
    let rec loop currentMap i =
        if i >= count then currentMap
        else
            let newMap = Map.add (students.[i].getId()) (students.[i].getScores()) currentMap
            loop newMap (i+1)
    loop Map.empty 0

现在,您可以充分灵活地生成值(它们不必是数组的一部分),并且避免可变变量在函数式编程中是非惯用的。理想情况下,就像在这种情况下,函数应该是tail-recursive以允许尾调用优化(并避免大输入的堆栈溢出)。