F# 如何获取序列中所有组的开始和结束索引

F# 如何获取序列中所有组的开始和结束索引,f#,functional-programming,F#,Functional Programming,我有一组布尔值,如下所示: [|true; false; true; true; true; false; true; false; true; true; true; false; true; true; false; true; true; true; false; true|] 我想要的是得到所有连续真群的指数: [|(0, 0); (2, 4); (6, 6); (8, 10); (12, 13); (15, 17); (19, 19)|] 我的功能解决方案是: let getBlo

我有一组布尔值,如下所示:

[|true; false; true; true; true; false; true; false; true; true; true; false;
true; true; false; true; true; true; false; true|]
我想要的是得到所有连续真群的指数:

[|(0, 0); (2, 4); (6, 6); (8, 10); (12, 13); (15, 17); (19, 19)|]
我的功能解决方案是:

let getBlocksIndices (r:bool[]) =
    let f = Array.append r [|false|]
    Seq.unfold(fun (p,i) ->
                    let nSt = f.[i],i+1
                    match p,f.[i] with
                    | false,true -> Some (i,nSt)
                    | true,false -> Some (i-1,nSt)
                    | _ -> Some (-1,nSt)

              ) (false,0)
    |> Seq.take f.Length
    |> Seq.filter (fun e -> e>=0 )
    |> Seq.pairwise
    |> Seq.mapi (fun i x -> if i%2=0 then Some(x) else None)
    |> Seq.choose id
    |> Array.ofSeq
但我觉得这么简单的任务太大了


您有更简单的选择吗?

最简单的方法-将其转换为列表并使用递归。通过这种方式,您可以在一次遍历列表中完成此操作

let rec blocklist l prevtrue idx =
    match l,prevtrue with
    |true ::t,None       ->               blocklist t (Some idx) (idx+1)
    |true ::t,ptrue      ->               blocklist t ptrue      (idx+1)
    |false::t,None       ->               blocklist t None       (idx+1)  
    |false::t,Some(sval) -> (sval,idx-1)::blocklist t None       (idx+1)
    |[],Some(t)          -> (t,idx-1)::[]
    |[],_                -> []

let blockify a = a |> Array.toList |> fun f -> blocklist f None 0

> blockify [|true; false; true; true; true; false; true; false; true; true; true; false;
- true; true; false; true; true; true; false; true|];;                                  
val it : (int * int) list =
  [(0, 0); (2, 4); (6, 6); (8, 10); (12, 13); (15, 17); (19, 19)]

另一种方法是将布尔值映射到数组索引,使用group by进行分组,最后计算范围

let grouped booleans = 
    booleans
    |> Seq.mapi (fun idx x -> if x then idx else -1)        // if true map to index else -1
    |> Seq.scan
            (fun prevIdx idx -> 
                match (prevIdx, idx) with                   // match current index with previous index
                |   _, -1       ->  -1
                |   -1, _       ->  idx
                |   _           ->  prevIdx)                
            -1
    |> Seq.groupBy id                                       // group by the repeating key
    |> Seq.filter (fun (key, group) -> key <> -1)           // remove the 'false group'   
    |> Seq.map (fun (key, group) -> (key, (group |> Seq.length) + key - 1)) // compute range
设分组布尔=
布尔运算
|>Seq.mapi(fun idx->if x then idx else-1)//if true映射到索引else-1
|>顺序扫描
(趣味prevIdx idx->
将(prevIdx,idx)与//将当前索引与以前的索引匹配
|   _, -1       ->  -1
|-1,->idx
|_ux->prevIdx)
-1
|>Seq.groupBy id//按重复键分组
|>Seq.filter(fun(key,group)->key-1)//删除'false group'
|>Seq.map(fun(key,group)->(key,(group |>Seq.length)+key-1))//计算范围

哇,你怎么这么快就想出了答案,我花了好几个小时,我怎么才能改变我使用thinkNice解决方案的方式。真令人印象深刻。