Search 排序和运行查询示例
我想获得一些关于如何使用F#/函数式编程来搜索列表中重复值的指针和/或示例代码 考虑以下用例: 给定一个列表/数组/日期序列和每个日期的最高温度,我想提取出连续n天温度高于给定阈值的初始日期 此类查询的另一个示例是搜索股票价格历史记录表/列表,查找在指定时间间隔(例如,至少30天)内超过给定阈值的价格。 在本例中,我要查找首次超过阈值的初始日期Search 排序和运行查询示例,search,f#,design-patterns,sequence,repeat,Search,F#,Design Patterns,Sequence,Repeat,我想获得一些关于如何使用F#/函数式编程来搜索列表中重复值的指针和/或示例代码 考虑以下用例: 给定一个列表/数组/日期序列和每个日期的最高温度,我想提取出连续n天温度高于给定阈值的初始日期 此类查询的另一个示例是搜索股票价格历史记录表/列表,查找在指定时间间隔(例如,至少30天)内超过给定阈值的价格。 在本例中,我要查找首次超过阈值的初始日期 TIA我可能会从一个效率较低但功能优雅的解决方案开始,该解决方案使用序列加窗功能(将序列转换为指定大小的连续组序列): 源代码 //创建指定大小的组 |
TIA我可能会从一个效率较低但功能优雅的解决方案开始,该解决方案使用
序列加窗功能(将序列转换为指定大小的连续组序列):
源代码
//创建指定大小的组
|>Seq.加窗所需长度
//将起始索引添加到序列中
|>Seq.mapi(乐趣i v->i,v)
//查找仅包含大于treshold的数字的所有组
|>顺序过滤器(乐趣(i,v)->v |>顺序过滤器(顺序图fst
这将返回所有此类组的索引,因此如果存在多个重叠组(即,与条件匹配的较大序列),则您将获得所有起始索引。您可能只需从结果中筛选连续数字,以仅获得组的第一个索引(使用Seq.fold
)
为了获得更有效的版本,您需要编写一个递归函数,在数组或列表上进行迭代。您可能需要记住(在函数参数中)在树型结构上找到最后一个值的时间。(这与命令式循环基本相同,只是您使用递归函数并在参数中保留状态).虽然我喜欢Tomas代码的简洁性,但我还是忍不住认为他所暗示的更高效的版本在这里是必须的,特别是如果实际的比较逻辑比简单的整数比较更昂贵的话。我提交以下摘要:
let findWindowBeginnings predicate minWindowSize data =
if minWindowSize < 2 then
invalidArg "minWindowSize" "minWindowSize must be greater than 1"
((None, []), data)
||> Seq.fold (fun (window, acc) x ->
if predicate x then
match window with
| Some (start, size) -> let size' = size + 1
let acc' = if size' = minWindowSize
then start::acc
else acc
Some (start, size'), acc'
| _ -> Some (x, 1), acc
else None, acc)
|> snd
|> List.rev
让findwindowbeginings谓词minWindowSize数据=
如果MinWindowsSize小于2,则
invalidArg“MinWindowsSize”MinWindowsSize必须大于1
((无,[]),数据)
||>顺序折叠(乐趣(窗口,附件)x->
如果谓词x那么
匹配窗口
|一些(开始,大小)->让大小“=大小+1
让acc'=如果大小'=最小窗口大小
然后启动::acc
其他acc
一些(开始,尺寸),acc'
|部分(x,1),根据
其他(无,acc)
|>snd
|>List.rev
日期+温度元组序列的用例如下所示:
let findHeatwaveBeginnings tempThreshold consecutiveDays data =
(consecutiveDays, data)
||> findWindowBeginnings (snd >> (<) tempThreshold)
// alternatively, if you're not a fan of point-free style code:
// findWindowBeginnings (fun (_, maxTemp) -> maxTemp > tempThreshold)
|> List.map fst
让FindHeatWaveBeginings尝试阈值连续日期数据=
(连续日期、数据)
||>FindwindowBeginings(snd>>(+1用于实际实现它!您介意将它发布到吗?人们经常会问类似的问题,并且通过键入工具提示阅读折叠更容易:-)
let findHeatwaveBeginnings tempThreshold consecutiveDays data =
(consecutiveDays, data)
||> findWindowBeginnings (snd >> (<) tempThreshold)
// alternatively, if you're not a fan of point-free style code:
// findWindowBeginnings (fun (_, maxTemp) -> maxTemp > tempThreshold)
|> List.map fst