检查列表中的连续值范围(F#)

时间:2014-01-24 17:12:35

标签: list f#

在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开始的索引号,甚至更好)

4 个答案:

答案 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
相关问题