我想过滤一个大的制表符分隔文件,其中包含基于另一个文件的坐标,我希望以功能样式进行。我想知道在F#中执行以下任务的有效/功能方法。
带一个带范围的文件(本质上是[group,start,end]的列表,另一个带有特定坐标的文件(基本上是[group,position])。通过仅输出[group,position]的网站来过滤第二个文件]在第一个文件的间隔内(例如,如果第一个文件包含[A,1,20],那么[A,5]将被输出,而[A,25]则不会。)
要过滤的文件要大到内存,有没有人知道一个时髦的功能方式来做到这一点?
答案 0 :(得分:3)
这实际上取决于问题的规模,即您希望在两个组中有多少东西。但是,作为起点,您可以使用Seq.groupBy
获取每个组的范围列表,然后使用Seq.exist
检查位置是否在任何范围内。
例如,给出以下输入:
let ranges = [ (1, 0, 5); (1, 10, 15 ) ]
let coords = [ (1, 3); (1, 7); (1, 12) ]
您可以创建一个字典,为您提供每个组的范围列表:
let byGroup =
ranges
|> Seq.groupBy (fun (g, _, _) -> g)
|> Seq.map (fun (k, v) -> k, Seq.map (fun (_, s, e) -> (s, e)) v)
|> dict
然后你可以过滤坐标,并且对于每个位置,扫描适当的范围以查看该位置是否属于其中任何一个:
coords
|> Seq.filter (fun (g, pos) ->
byGroup.[g] |> Seq.exists (fun (l, h) -> pos >= l && pos <= h))
如果范围的数量非常高,这可能不会起作用,但对于较小的示例,它应该足够好。对于更大的数据,您可能想要创建某种类似二叉树的结构(您可以在其中搜索范围),但这是一个更复杂的问题,更多的是关于算法而不是关于F#。