我已经制作了以下F#函数,它将从网页的html内容中获取一个url:
let getPicUrl (urlContents : string) =
let START_TOKEN = "jpg_url="
let startIndex = urlContents.IndexOf(START_TOKEN)
let endIndex = urlContents.IndexOf("&", startIndex)
let s = startIndex + START_TOKEN.Length
let l = endIndex-startIndex-START_TOKEN.Length
urlContents.Substring(s, l)
最后一行urlContents.Substring(s, l)
实际上只需要s
和l
,所以我想知道是否可以将此函数的一部分重构为一些内部函数,所以我想让我的意图更清楚。理想情况下getPicUrl
只有2 let
条指令,s
和l
,其他所有指令都是let
指令的内部定义。如果这可以以任何方式实现或不是另一个故事..
我现在能够想到改善上述代码的唯一明显方法是切换endIndex
的地方,以便我们拥有
let getPicUrl (urlContents : string) =
let START_TOKEN = "jpg_url="
let startIndex = urlContents.IndexOf(START_TOKEN)
let s = startIndex + START_TOKEN.Length
let l =
let endIndex = urlContents.IndexOf("&", startIndex)
endIndex-startIndex-START_TOKEN.Length
urlContents.Substring(s, l)
但我一直想知道是否有更清晰的方法来组织这个函数的let
定义。
答案 0 :(得分:3)
首先,你的功能是错误的。一个不匹配的字符串会使它变得脾气暴躁。
我喜欢这种类型的正则表达式。有了这种活跃的模式:
open System.Text.RegularExpressions
let (|Regex|_|) pattern input =
let m = Regex.Match(input, pattern)
if m.Success then Some(List.tail [for g in m.Groups -> g.Value])
else None
你可以这样做:
let tryGetPicUrl = function
| Regex @"jpg_url=([^&]+)&" [url] -> Some url
| _ -> None
您还可以将原始方法转变为活动模式:
let (|Between|_|) (prefix:string) (suffix:string) (value:string) =
match value.IndexOf(prefix) with
| -1 -> None
| s ->
let n = s + prefix.Length + 1
match value.IndexOf(suffix, n) with
| -1 -> None
| e -> Some (value.Substring(n, e - n))
并且做:
let tryGetPicUrl = function
| Between "jpg_url" "&" url -> Some url
| _ -> None
答案 1 :(得分:2)
你可以这样写:
let getPicUrl (urlContents : string) =
let s =
let START_TOKEN = "jpg_url="
let startIndex = urlContents.IndexOf(START_TOKEN)
startIndex + START_TOKEN.Length
let l =
let endIndex = urlContents.IndexOf("&", s)
endIndex-s
urlContents.Substring(s, l)
答案 2 :(得分:0)
另一个选择是使用string的split方法(我希望字符串不会太长,因为这会影响性能)并使用选项类型来指示是否找到了URL。
let getPicUrl (urlContents : string) =
let splitAndGet n (sep:string) (str:string) =
let spl = str.Split([|sep|],StringSplitOptions.None)
match spl.Length with
| x when x > n -> Some (spl.[n])
| _ -> None
match urlContents |> splitAndGet 1 "jpg_url=" with
| Some str -> str |> splitAndGet 0 "&"
| _ -> None