IEnumerable.GetEnumerator().NET 标准库中仍然有一些东西只向外界公开旧式迭代器,这对 F# seq 处理风格不太友好。我正在快速谷歌搜索如何将 a 的结果组Regex.Match(...)放入我可以处理的列表中,但没有找到任何内容。
我有这个:
open System.Text.RegularExpressions
let input = "args=(hello, world, foo, bar)"
let mtc = Regex.Match( input, "args=\(([\w\s,]+)\)" )
Run Code Online (Sandbox Code Playgroud)
我想要的是mtc.Groups作为 seq 或作为列表进行访问,但它不允许这样做,因为它是 ye olde ICollection,它只公开一个GetEnumerator()方法。所以虽然你可以做
mtc.Groups.[1].Value
Run Code Online (Sandbox Code Playgroud)
你不能做
mtc.Groups |> Seq.skip 1 // <=== THIS QUESTION IS ABOUT HOW TO ACHIEVE THIS
Run Code Online (Sandbox Code Playgroud)
因为这导致
error FS0001: The type 'Text.RegularExpressions.GroupCollection' is not compatible with the type 'seq<'a>
Run Code Online (Sandbox Code Playgroud)
(为了清楚起见,GroupCollection实现了ICollection,它是 的子接口IEnumerable。)
所以问题是:如何巧妙地将 a 转换GetEnumerator()为 seq?
答案其实并不复杂,只是为下一个在谷歌上搜索快速答案的人提供的。这个想法是将可怕的命令性包装在seq {...}表达式中,然后将结果转换seq<obj>为您碰巧知道的结果。
seq { let i = mtc.Groups.GetEnumerator() in while i.MoveNext() do yield i.Current }
|> Seq.cast<Text.RegularExpressions.Group>
|> Seq.map (fun m -> m.Value)
|> List.ofSeq
Run Code Online (Sandbox Code Playgroud)
当对上述输入运行时,会产生所需的输出:
val input : string = "args=(hello, world, foo, bar)"
val mtc : Match = args=(hello, world, foo, bar)
val it : string list = ["args=(hello, world, foo, bar)"; "hello, world, foo, bar"]
Run Code Online (Sandbox Code Playgroud)
正如我所说,我将其放在这里供下一个谷歌搜索答案,因此欢迎改进、建议、反对票、欺骗标志。
编辑:根据第一条评论中的建议,Seq.cast足够聪明,可以IEnumerable直接吃 s 。所以 seq 表达式根本没有必要,答案就是Seq.cast<Text.RegularExpressions.Group>!让我知道我是否应该删除这个问题。