.NET标准库中还有一些东西只会将旧学校IEnumerable.GetEnumerator()
迭代器暴露给外部世界,这对F#seq处理样式不是很友好。我正在快速谷歌如何将Regex.Match(...)
的结果组放入我可以处理的列表中,但没有找到任何内容。
我有这个:
open System.Text.RegularExpressions
let input = "args=(hello, world, foo, bar)"
let mtc = Regex.Match( input, "args=\(([\w\s,]+)\)" )
我想要的是访问mtc.Groups
作为seq或列表,但它不允许这样做,因为它是一个ICollection
,它只暴露GetEnumerator()
1}}方法。所以尽管你可以做到
mtc.Groups.[1].Value
你做不到
mtc.Groups |> Seq.skip 1 // <=== THIS QUESTION IS ABOUT HOW TO ACHIEVE THIS
因此导致
error FS0001: The type 'Text.RegularExpressions.GroupCollection' is not compatible with the type 'seq<'a>
(为清楚起见,GroupCollection
实现ICollection
,这是IEnumerable
的子接口。)
所以问题是:我如何巧妙地将GetEnumerator()
变成seq?
答案 0 :(得分:3)
答案实际上并不复杂,只是在谷歌搜索快速回答的下一个人。我们的想法是在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
在上述输入上运行时,会产生所需的输出:
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"]
正如我所说的那样,我将它放在这里作为答案的下一位标题,所以欢迎改进,建议,downvotes,dupe标志。
编辑:根据第一条评论中的建议,Seq.cast
非常聪明,可以直接吃IEnumerable
个。所以seq表达式根本就没有必要,答案只是Seq.cast<Text.RegularExpressions.Group>
!如果我应该删除这个问题,请告诉我。