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解决方案的方式。真令人印象深刻。