匹配空序列
Match with empty sequence
我正在学习 F#,并且已经开始使用序列和 match
表达式。
我正在编写一个网络抓取工具,它正在浏览 HTML 类似于以下内容,并使用 paging
[=] 在父 <span>
中获取最后一个 URL 33=].
<html>
<body>
<span class="paging">
<a href="http://google.com">Link to Google</a>
<a href="http://TheLinkIWant.com">The Link I want</a>
</span>
</body>
</html>
我尝试获取最后一个 URL 如下:
type AnHtmlPage = FSharp.Data.HtmlProvider<"http://somesite.com">
let findMaxPageNumber (page:AnHtmlPage)=
page.Html.Descendants()
|> Seq.filter(fun n -> n.HasClass("paging"))
|> Seq.collect(fun n -> n.Descendants() |> Seq.filter(fun m -> m.HasName("a")))
|> Seq.last
|> fun n -> n.AttributeValue("href")
但是,当我正在搜索的 class 不在页面中时,我 运行 遇到了问题。特别是我收到 ArgumentExceptions 消息:Additional information: The input sequence was empty.
我的第一个想法是构建另一个匹配空序列并在页面上找不到 paging
class 时返回空字符串的函数。
let findUrlOrReturnEmptyString (span:seq<HtmlNode>) =
match span with
| Seq.empty -> String.Empty // <----- This is invalid
| span -> span
|> Seq.collect(fun (n:HtmlNode) -> n.Descendants() |> Seq.filter(fun m -> m.HasName("a")))
|> Seq.last
|> fun n -> n.AttributeValue("href")
let findMaxPageNumber (page:AnHtmlPage)=
page.Html.Descendants()
|> Seq.filter(fun n -> n.HasClass("paging"))
|> findUrlOrReturnEmptyStrin
我现在的问题是 Seq.Empty
不是文字,不能在模式中使用。大多数具有模式匹配的示例在其模式中指定空列表 []
所以我想知道:如何使用类似的方法来匹配空序列?
您可以使用 when
守卫来进一步限定案例:
match span with
| sequence when Seq.isEmpty sequence -> String.Empty
| span -> span
|> Seq.collect (fun (n: HtmlNode) ->
n.Descendants()
|> Seq.filter (fun m -> m.HasName("a")))
|> Seq.last
|> fun n -> n.AttributeValue("href")
ildjarn 是正确的,在这种情况下,if...then...else
可能是更易读的选择。
ildjarn 在评论中给出的建议是一个很好的建议:如果您觉得使用 match
会创建更具可读性的代码,那么制作一个活动模式来检查空序列:
let (|EmptySeq|_|) a = if Seq.isEmpty a then Some () else None
let s0 = Seq.empty<int>
match s0 with
| EmptySeq -> "empty"
| _ -> "not empty"
运行 在 F# 交互中,结果将是 "empty"
.
根据@rmunn 的回答,您可以创建一个更通用的序列相等活动模式。
let (|Seq|_|) test input =
if Seq.compareWith Operators.compare input test = 0
then Some ()
else None
match [] with
| Seq [] -> "empty"
| _ -> "not empty"
使用保护条款
match myseq with
| s when Seq.isEmpty s -> "empty"
| _ -> "not empty"
我正在学习 F#,并且已经开始使用序列和 match
表达式。
我正在编写一个网络抓取工具,它正在浏览 HTML 类似于以下内容,并使用 paging
[=] 在父 <span>
中获取最后一个 URL 33=].
<html>
<body>
<span class="paging">
<a href="http://google.com">Link to Google</a>
<a href="http://TheLinkIWant.com">The Link I want</a>
</span>
</body>
</html>
我尝试获取最后一个 URL 如下:
type AnHtmlPage = FSharp.Data.HtmlProvider<"http://somesite.com">
let findMaxPageNumber (page:AnHtmlPage)=
page.Html.Descendants()
|> Seq.filter(fun n -> n.HasClass("paging"))
|> Seq.collect(fun n -> n.Descendants() |> Seq.filter(fun m -> m.HasName("a")))
|> Seq.last
|> fun n -> n.AttributeValue("href")
但是,当我正在搜索的 class 不在页面中时,我 运行 遇到了问题。特别是我收到 ArgumentExceptions 消息:Additional information: The input sequence was empty.
我的第一个想法是构建另一个匹配空序列并在页面上找不到 paging
class 时返回空字符串的函数。
let findUrlOrReturnEmptyString (span:seq<HtmlNode>) =
match span with
| Seq.empty -> String.Empty // <----- This is invalid
| span -> span
|> Seq.collect(fun (n:HtmlNode) -> n.Descendants() |> Seq.filter(fun m -> m.HasName("a")))
|> Seq.last
|> fun n -> n.AttributeValue("href")
let findMaxPageNumber (page:AnHtmlPage)=
page.Html.Descendants()
|> Seq.filter(fun n -> n.HasClass("paging"))
|> findUrlOrReturnEmptyStrin
我现在的问题是 Seq.Empty
不是文字,不能在模式中使用。大多数具有模式匹配的示例在其模式中指定空列表 []
所以我想知道:如何使用类似的方法来匹配空序列?
您可以使用 when
守卫来进一步限定案例:
match span with
| sequence when Seq.isEmpty sequence -> String.Empty
| span -> span
|> Seq.collect (fun (n: HtmlNode) ->
n.Descendants()
|> Seq.filter (fun m -> m.HasName("a")))
|> Seq.last
|> fun n -> n.AttributeValue("href")
ildjarn 是正确的,在这种情况下,if...then...else
可能是更易读的选择。
ildjarn 在评论中给出的建议是一个很好的建议:如果您觉得使用 match
会创建更具可读性的代码,那么制作一个活动模式来检查空序列:
let (|EmptySeq|_|) a = if Seq.isEmpty a then Some () else None
let s0 = Seq.empty<int>
match s0 with
| EmptySeq -> "empty"
| _ -> "not empty"
运行 在 F# 交互中,结果将是 "empty"
.
根据@rmunn 的回答,您可以创建一个更通用的序列相等活动模式。
let (|Seq|_|) test input =
if Seq.compareWith Operators.compare input test = 0
then Some ()
else None
match [] with
| Seq [] -> "empty"
| _ -> "not empty"
使用保护条款
match myseq with
| s when Seq.isEmpty s -> "empty"
| _ -> "not empty"