【发布时间】:2016-01-10 08:16:34
【问题描述】:
给定一组int*string的字典,其中第一个是“主要”,我想回答这个问题:
对于所有其他字典,它们全部是否具有与主字典相同的键值?
我目前通过以下方式实现了这一目标:
let allSame = primary @ remaining
|> Seq.groupBy (fun (pos, _) -> pos)
|> Seq.map (fun (pos, items) -> (pos, items |> Seq.map (fun (_, name) -> name) |> Seq.distinct |> List.ofSeq))
|> Seq.exists (fun (_, names) -> names.Length > 1))
我想知道是否有更惯用的方法来实现这一点?
在分组int * (int * string) list 中重复pos,然后必须减少到int * string list 似乎有点多余,但不幸的是groupBy 不提供价值投影过载。
编辑
给定一堆简化结构的项目(字段){SortOrder:int;Name:string;...}
我要去:Field list -> (int * string) list
“主要”只是列表的开头,我选择哪个作为“主要”并不重要,因为我只关心是否所有具有相同位置的字段也具有相同的名称。
这就是为什么我按位置分组,然后减少到一个不同的名称列表,然后只计算条目(>1 显然意味着一些分歧)。
最终解决方案
这就是我最终得到的结果:
let primary = getFields <| fst x
let allSame = (primary) @ ((tail |> List.map (fun (m,_) -> getFields m)) |> List.collect (fun e -> e))
|> Seq.sortBy (fun (pos, _) -> pos)
|> Seq.pairwise
|> Seq.forall (fun ((_,namex),(_,namey)) -> Seq.forall2 (=) namex namey)
if allSame then
Some (fst x)
else
failwith "Some error message here"
【问题讨论】:
-
在这种情况下,我将只使用
System.Collection.Generic.Dictionarys,检查键计数并测试所有键的值是否匹配 - 你的似乎有些奇怪 - 它不应该是Seq.forall取而代之的是 - 即使您的输入字典的每个键都有多个值(另一个缺失)怎么办? -
除此之外 - 对两者进行排序,然后压缩然后比较两个组件中匹配部分的元组似乎也是合理的(O(n log n))
-
我稍微简化了一些,
Seq.exists出现在实际代码的后面,我测试了不同的键数。
标签: dictionary f# idioms