在10个数字的排序列表中,我想知道是否有5个连续数字在一定范围内。供参考:这被称为寻找“stellium”(天文学术语,关于行星的位置)。
如果列表是:
let iList = [15; 70; 72; 75; 80; 81; 120; 225; 250; 260]
我想要一个功能
let hasStellium iStellSize iStellRange iList
将返回
hasStellium 5 20 iList = true
列表已经排序,所以我可以继续使用笨重的if-then语句(例如“检查元素1和5是否小于20个单位,检查元素2和6是否满足条件”等。
let hasStellium iStellSize iStellRange iList=
if
iList.[iStellSize-1] - iList.[0] < iStellRange ||
iList.[iStellSize] - iList.[1] < iStellRange
then true
else false
但必须有更优雅的方式,这也允许其他的stellium尺寸,而无需手动添加if-then线。
非常感谢你的帮助!
(如果该函数可以返回stellium开始的索引号,甚至更好)
答案 0 :(得分:3)
只需合并两个标准库函数:
let hasStellium iStellSize iStellRange iList =
iList |> Seq.windowed iStellSize
|> Seq.tryFindIndex (fun s -> (s.[iStellSize - 1] - s.[0] < iStellRange))
如果找不到这样的范围,则返回None
,否则Some x
其中x
- 范围开始索引。
答案 1 :(得分:2)
你走了。它返回int option
,它是范围的起始索引,如果找不到,则返回None
。
let tryFindStelliumIndex iStellSize iStellRange iList =
let rec findRange i n = function
| _ when (n + 1) = iStellSize -> Some (i - n)
| prev::cur::tail when (cur - prev) < iStellRange -> findRange (i + 1) (n + 1) (cur::tail)
| _::tail -> findRange (i + 1) 0 tail
| _ -> None
findRange 0 0 iList
答案 2 :(得分:1)
使用Seq函数的另一个变体:
let hasStellium size range l =
Seq.zip l (l |> Seq.skip (size - 1))
|> Seq.tryFindIndex (fun p -> snd p - fst p < range)
答案 3 :(得分:0)
不得不用可变变量破解“早期返回”,但这是一个粗略的版本
let mutable found = false
for i = 0 to (iList |> List.length - iStellSize) do
if iList.[i + iStellSize] - iList.[i] <= iStellRange then //Did you mean < or <=?
found <- true
found