在学习F#+ Linq的awesomness的过程中,我遇到了一个问题,我无法解决(很好)使用函数,OOP和Linq语法,是否有人愿意帮助?
让我们说我的输入是以下顺序:
let db = seq [ ("bob", 90, ['x';'y'])
               ("bob", 70, ['z'])
               ("frank", 20, ['b'])
               ("charlie", 10, ['c']) ]
行可以读取例如"学生鲍勃已经注册了x,y在第90学期"
我需要的是这个:
[ ("bob",  [90; 70],  ['x'; 'y'; 'z']) 
  ("frank",    [20],  ['b'])
  ("charlie",  [10],  ['c']) ]
这将改为"鲍勃已完成学期90,70并取x,y,z".
Linq/Relational方法通常为这些问题提供最可读的解决方案.但我能想到的最好的是:
type Student = string
type Semester = int
type Class = char
let restructure (inp:seq<Student * Semester * Class list>) = query {
        for (student, semester, classes) in inp do
        groupValBy (semester,classes) student into data 
        yield (data.Key, Seq.map fst data, Seq.collect snd data)
    }
哪个既不可读,也不快,也不漂亮,也不惯用,并且由于F#的复杂性要求我写输入类型签名...
某些GroupMultipleValBy函数有更好的方法吗?非常感谢你!
如果你能坚持使用"经典"F#代码,你可以用更易读的方式重写它(特别是使用本地代码使代码更具可读性)
好吧,看起来Tomas打败了我,我们已经走了大致相同的道路中间有些"怪癖"
let restructure inp =
  // could have been defined at a more global scope as helpers
  let fst3 (x, _, _) = x
  let flip f y x = f x y
  let folder cont (student, semester, classes) (_, semesters, allClasses) =
    cont (student, semester :: semesters, classes @ allClasses)
  let initialState = "", [], []
  inp
  |> Seq.groupBy fst3
  |> Seq.map (snd >> flip (Seq.fold folder id) initialState)
难以理解的是folder,为了使学期保持在所需的顺序中,我们要么必须添加额外的步骤来反转该部分,要么使用延续来完成
flip添加使用的那个(以及使用它保持点免费)@使我认为Tomas代码"更好"(但他的回答使得学期和课程seq代替list)
附录
这里的Tomas代码以我发现更具可读性的方式编写(但这是一个品味问题),并且可能对操作的内容更加不可知,尽管它更长
[不需要任何东西它的答案很好]
let restructure inp =
  // could have been defined at a more global scope as helpers
  let fst3 (x, _, _) = x
  let snd3 (_, y, _) = y
  let trd3 (_, _, z) = z
  let mapping (key, values) =
    key,
    // replace with commented part to have lists instead of seqs
    values |> Seq.map snd3, //[ for value in values -> snd3 value ],
    values |> Seq.collect trd3 //[ for value in values do yield! trd3 value ]
  inp
  |> Seq.groupBy fst3
  |> Seq.map mapping
| 归档时间: | 
 | 
| 查看次数: | 73 次 | 
| 最近记录: |