如何在文本中查找整数

gis*_*orx 0 string f# function

帮助我弄清楚如何处理文本

我有一个字符串,例如:“word1 number:word2”例如:“结果0:好”或“结果299:坏”

我需要打印未定义/低或高

当 string 为 null 时,打印 Undefined

当数字0-15时,打印Low

当数字 >15 时,打印 High

type GetResponse = 
{ 
  MyData: string voption
  ErrorMessage: string voption }

val result: Result<GetResponse, MyError>
Run Code Online (Sandbox Code Playgroud)

然后我尝试:

MyData =
match result with
| Ok value ->
    if (value.Messages = null) then
        ValueSome "result: Undefined"
    else
        let result =
            value.Messages.FirstOrDefault(
                (fun x -> x.ToUpperInvariant().Contains("result")),
                "Undefined"
            )

        if (result <> "Undefined") then
            ValueSome result
        else
            errors.Add("We don't have any result")
            ValueNone
| Error err ->
    errors.Add(err.ToErrorString)
    ValueNone
ErrorMessage =
  if errors.Any() then
   (errors |> String.concat ", " |> ValueSome)
  else
   ValueNone
Run Code Online (Sandbox Code Playgroud)

但我不知道gow检查字符串号,也许有某种方法可以打印这个而不需要十亿个if?

bri*_*rns 5

解析很快就会变得复杂。我建议使用FParsec来简化逻辑并避免错误。一个基本的解析器似乎可以满足您的需求:

open System
open FParsec

let parseWord =
    manySatisfy Char.IsLetter

let parseValue =
    parseWord              // parse any word (e.g. "result")
        >>. spaces1        // skip whitespace
        >>. puint32        // parse an unsigned integer value
        .>> skipChar ':'   // skip colon character
        .>> spaces         // skip whitespace
        .>> parseWord      // parse any word (e.g. "Good")
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样使用它:

type ParserResult = Undefined | Low | High

let parse str =
    if isNull str then Result.Ok Undefined
    else
        match run parseValue str with
            | Success (num, _ , _) ->
                if num <= 15u then Result.Ok Low
                else Result.Ok High
            | Failure (errorMsg, _, _) ->
                Result.Error errorMsg

parse null |> printfn "%A"                // Ok Undefined
parse "result 0: Good" |> printfn "%A"    // Ok Low
parse "result 299: Bad" |> printfn "%A"   // Ok High
parse "invalid input" |> printfn "%A"     // Error "Error in Ln: 1 Col: 9 ... Expecting: integer number"
Run Code Online (Sandbox Code Playgroud)

FParsec 肯定有一个学习曲线,但我认为它值得添加到您的工具带中。


小智 5

我同意 Brian 的观点,即解析很快就会变得非常棘手。但是,如果您有一些完善的输入格式,并且不太喜欢编写复杂的解析器,那么好的旧正则表达式可以派上用场;)

这是我对这个问题的看法 - 请注意,它还有很大的改进空间,这只是一个概念证明:

open System.Text.RegularExpressions

let test1 = "result 0: Good"
let test2 = "result 299: Bad"
let test3 = "some other text"

type ParserResult = 
    | Undefined 
    | Low of int 
    | High of int


let (|ValidNumber|_|) s = 
    //https://learn.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regex?view=net-6.0
    let rx = new Regex("(\w\s+)(\d+)\:(\s+\w)") 
    let matches = rx.Matches(s)
    if matches.Count > 0 then
        let groups = matches.[0].Groups |> Seq.toList
        match groups with
        | [_; _; a; _] -> Some (int a.Value)
        | _ -> None
    else
        None

let parseMyString str = 
    match str with
    | ValidNumber n when n < 16 -> Low n
    | ValidNumber n -> High n
    | _ -> Undefined

//let r = parseMyString test1
printfn "%A" (parseMyString test1)
printfn "%A" (parseMyString test2)
printfn "%A" (parseMyString test3)
Run Code Online (Sandbox Code Playgroud)

如果找到输入字符串的匹配项,则活动模式 ValidNumber 返回 Some 数字,否则返回 None。parseMyString 函数使用模式和防护来初始化最终的 ParserOutput 值。

  • `\A` 是字符串开头,`\z` 是字符串结尾。它类似于“^”和“$”。但后者可以改变行为,具体取决于 Regex 是否启用了多行开关。 (3认同)
  • 最好将 `\A` 和 `\z` 添加到正则表达式中。`\A(\w\s+).....\z` 进一步限制它。如果它总是以“结果”开头,甚至比 `\Aresult\s+(\d+):\s+(.*)\z` (2认同)