代码:
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循环将项添加到地图中,我的学生对象数组用于获取我需要的相应数据。我将能够给它一个字符串并取回该学生的成绩。我知道这是一个我正在研究的奇怪问题,但我最初需要尝试一些简单的事情。
答案 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以允许尾调用优化(并避免大输入的堆栈溢出)。