我有一组bools分组如下:
[|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
但我认为这对于这么简单的任务来说太大了,
你有更简单的选择吗?
答案 0 :(得分:2)
最简单的方法 - 将其转换为列表并使用递归。通过这种方式,您可以在列表中单次传递
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)]
答案 1 :(得分:0)
另一种方法 - 将布尔值映射到数组索引,使用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