Dictionary F#基础:地图地图?
我的教授为我们的课堂提供了解决问题的提示,并建议我们首先使用以下方法对课堂进行建模:Dictionary F#基础:地图地图?,dictionary,f#,Dictionary,F#,我的教授为我们的课堂提供了解决问题的提示,并建议我们首先使用以下方法对课堂进行建模: let students = Map.add 1 Map.empty Map.empty 世界从一个学生开始(由他们的ID表示,例如1),每个学生都有许多班级ID,每个班级都有一个与他们相关的等级(a+,F等) 我很难理解这段代码的真正含义,我只懂一张地图。比如说 let student = Map.add 43 "A+" 如何在建议的版本中添加新的“学生”或“classID/年级”并返回新地图 接下来,
let students = Map.add 1 Map.empty Map.empty
世界从一个学生开始(由他们的ID表示,例如1),每个学生都有许多班级ID,每个班级都有一个与他们相关的等级(a+,F等)
我很难理解这段代码的真正含义,我只懂一张地图。比如说
let student = Map.add 43 "A+"
如何在建议的版本中添加新的“学生”或“classID/年级”并返回新地图
接下来,我将如何在这样的映射上访问/迭代元素?
谢谢,这里的函数式编程初学者,真的很吃力。好的,我知道如何添加到它,我只需要给每个映射一个表名,例如
let students = Map.add 1 (Map.add 43 "A+" Map.empty) Map.empty
我可以使用Let student1=Map.find 1 students
获得特定学生的地图
let grades = Map.empty<string,string>
let students = Map.empty<int,Map<string,string>>
let students = students.Add(1,grades.Add("class1","A").Add("class2","B"))
let students = students.Add(2,grades.Add("class3","A").Add("class4","C"))
2) 您可以通过map.iter或map.map在地图上迭代:
let classes' = classes |> Map.ofList
防止等级膨胀:-)
请看一下:和
虽然我能理解答案,但在尝试s952163(重复变量声明)中的答案时出现语法错误,因此我想发布一个可能有用的替代方案 希望代码中的注释能够解释这些建议
// Alias the types for ease of use later
let studentRecords = Map.empty<int, Map<string, string>>
let grades = Map.empty<string, string>
// create a collection of students
// (note use of aliases here but could use Map.empty<>.Add if preferred)
let students =
studentRecords
.Add(1, grades.Add("class1", "A").Add("class2", "B"))
.Add(2, grades.Add("class1", "D").Add("class2", "C"))
// can index into the student map by the integer key
// and print out the value of the embedded map based on it's key
let studentId = 1
let className = "class2"
let student1 = students.[studentId]
printfn
"StudentId: %i obtained %s in %s"
studentId
student1.[className]
className
// can use Map.map to iterate and obtain some specifics from the embedded map
// eg. This prints out all students and their grades for "class2"
printfn "%s results:" className
students
|> Map.map (fun key value -> printfn "Student %i - %s" key value.[className] )
//为这些类型添加别名以便于以后使用
让studentRecords=Map.empty
让grades=Map.empty
//创建一个学生集合
//(注意此处使用别名,但如果愿意,可以使用Map.empty.Add)
让学生=
学生记录
添加(1,等级添加(“1类”、“A类”)。添加(“2类”、“B类”))
添加(2,等级添加(“1类”、“D类”)。添加(“2类”、“C类”))
//可以通过整数键索引到学生地图中
//并根据其键打印出嵌入地图的值
让studentId=1
让className=“class2”
让学生1=学生。[studentId]
printfn
“学生ID:%i在%s中获得了%s”
学生
学生1。[类名]
类名
//可以使用Map.Map迭代并从嵌入的Map中获取一些细节
//这个打印出“2班”的所有学生和他们的成绩
printfn“%s结果:”类名称
学生
|>Map.Map(有趣的键值->printfn“学生%i-%s”键值。[className])
我也刚刚开始学习f#,所以s952163的答案确实帮助我达到了上述目标。希望它能为回答这个问题的人提供进一步的见解。关于你的问题,什么是
let student=Map.add 43“A+”
的意思是:Map.add
包含3个参数,一个键、一个值和一个要添加的映射<因此,code>student是一个函数,它获取一个映射,并返回一个新映射,该映射还包含一个键43
,值“a+”
关于数据类型的另一个建议是:等级不是自由形式的字符串。通过使用与域密切匹配的数据类型,可以使代码更安全。例如,对于等级,可以使用
type Grade =
| APlus
| A
| B
| F // Omitting the other grades for brevity
如果您做到了这一点并且很好地使用了模式匹配,那么编译器将在检查代码中是否存在您可能忽略的特殊情况方面提供很大帮助。同样,可以避免将标识学生的整数与标识类的整数混淆
[<Measure>]
type StudentID
[<Measure>]
type ClassID
// A class that contains 2 students with IDs 1 and 2
let initialClass = Set.ofList [ 1<StudentID>; 2<_> ]
// Adding a student with ID 3 gives a new class
let classWithNewStudent = initialClass.Add 3<_>
你确定这行是你想的吗:
let student=Map.add 43“A+”
@s952163抱歉,它可能应该是let student=Map.add 43“A+”Map.empty
返回一个新的Map,键是43,值是A+。但我想我需要一张地图。所以应该是Map.add1(Map.add43“A+”)。因此,这将是一个值为map的map,不确定语法或如何添加到它,或者如何实际访问它。它不构成map:)你认为这两者之间的区别是什么:让学生=map.add 43“a+”
和map.empty.add(43,“a+”
(因为你从map.empty开始)。你能看到字体符号吗?是的。确切地但您不会一直将其添加到空地图中。如果你想成长,你可以将它添加回学生地图。因此,一旦知道如何添加到地图,是什么阻止您添加地图,其中键是学生id,值是另一个地图,键是一个类,值是分数?如果时间太长,我们可以用它来聊天,现在你有足够的声誉;)对但地图的一个特点是它是不可变的。我猜你想把它添加到你的地图上。让我再回答一个问题。@s952163我必须有一个版本是不可变的(我已经实现了这一半),使用fold和一个可变的,用于显示性能差异。对不起,我是新手,我该如何给你另一个答案?我添加了另一个答案和一些澄清。太好了:)这就是我要找的,非常感谢,非常感谢。感谢你的额外输入,是一个很大的帮助值在F#中是不可变的(除非用可变的修饰),但你应该能够隐藏变量(将新变量指定给旧名称)。例如,如果您在FSI中以块的形式执行它,则可能会发生这种情况。您可以将其包装在函数中。是的。请注意,到目前为止,我一直在使用FSI。谢谢您提供的额外信息!
type Grade =
| APlus
| A
| B
| F // Omitting the other grades for brevity
[<Measure>]
type StudentID
[<Measure>]
type ClassID
// A class that contains 2 students with IDs 1 and 2
let initialClass = Set.ofList [ 1<StudentID>; 2<_> ]
// Adding a student with ID 3 gives a new class
let classWithNewStudent = initialClass.Add 3<_>
let gradesForClass101 =
[ (1<StudentID>, APlus); (2<_>, F) ]
|> Map.ofList
let gradesForClass206 =
[ (3<StudentID>, B); (2<_>, F) ]
|> Map.ofList
// Here's the student function from your question:
let addStudent43 = Map.add 43<_> APlus
// This is now a new map that contains students 2, 3, 43
let moreGrades = addStudent43 gradesForClass206
// This is now a map of maps: For each class, we store
// a mapping classID -> grades that all students got in this class
let gradesPerClass =
[ (206<ClassID>, gradesForClass206); (101<_>, gradesForClass101)]
|> Map.ofList
// Compute all grades that student 2 gets
let gradesViaFold =
gradesPerClass
|> Map.fold (fun state _ grades ->
// We don't need the classID here, so use _ as the second arg
match grades.TryFind 2<_> with
// We found a grade for student 2: Add it at the beginning of the list
| Some grade -> grade :: state
// Student 2 did not get a grade for this class: leave the state
// (grades seen so far) empty
| _ -> state
) []
let printGrades g = Seq.iter (printfn "Grade %A") g
do printGrades gradesViaFold
// Compute all grades that student 2 gets, via a mutable list
let gradesMutable = System.Collections.Generic.List<Grade>()
do
gradesPerClass
|> Map.iter (fun _ grades ->
match grades.TryFind 2<_> with
| Some grade -> gradesMutable.Add grade
| _ -> ()
)
printGrades gradesMutable
// A map from classID to grade for student 2
let gradesForStudent2 =
gradesPerClass
|> Seq.choose (fun (KeyValue(classID, grades)) ->
match grades.TryFind 2<_> with
| Some grade -> Some (classID, grade)
| _ -> None
)
|> Map.ofSeq