首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >F#如何使用户输入:分离数字,单位,单词?

F#如何使用户输入:分离数字,单位,单词?
EN

Stack Overflow用户
提问于 2011-01-11 03:08:23
回答 2查看 475关注 0票数 3

我对F#相当陌生,但在过去的几个星期里,我一直在阅读参考资料。我希望处理一个用户提供的输入字符串,识别和分离组成元素.例如,对于此输入:

XYZ酒店:6晚,220欧元/晚,外加17.5%的税

输出应该类似于一个元组列表:

("XYZ",Word);(“旅馆:”,Word); ("6",编号);(“夜晚”,字); ("at",操作员);("220",编号); ("EUR",CurrencyCode);("/",操作员);(“夜”,单词); (“+”,操作员);("17.5",数字);("%",PerCent);(“税”,词)

因为我处理的是用户输入,所以它可能是任何东西。因此,期望用户遵守语法是不可能的。我想要识别数字(可以是整数、浮点数、负.)、度量单位(可选,但可以包括SI或帝国物理单位、货币代码、计数,例如我的示例中的“夜/秒”)、数学运算符(作为数学符号或包括"at“per”、" of“、”折扣“等在内的单词)和所有其他单词。

我的印象是我应该使用主动模式匹配--这是对的吗?--但我不确定如何开始。任何指向适当参考材料或类似例子的指示都是很好的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-01-11 03:48:50

我使用FParsec库编写了一个示例。这个例子一点也不健壮,但是它给出了一个关于如何使用FParsec的很好的图片。

代码语言:javascript
复制
type Element =
| Word of string
| Number of string
| Operator of string
| CurrencyCode of string
| PerCent  of string    

let parsePerCent state =
    (parse {
        let! r = pstring "%"
        return PerCent r
    }) state

let currencyCodes = [|
    pstring "EUR"
|]

let parseCurrencyCode state =
    (parse {
        let! r = choice currencyCodes
        return CurrencyCode r
    }) state

let operators = [|
    pstring "at"
    pstring "/"
|]

let parseOperator state =
    (parse {
        let! r = choice operators
        return Operator r
    }) state

let parseNumber state =
    (parse {
        let! e1 = many1Chars digit
        let! r = opt (pchar '.')
        let! e2 = manyChars digit
        return Number (e1 + (if r.IsSome then "." else "") + e2)
    }) state

let parseWord state =
    (parse {
        let! r = many1Chars (letter <|> pchar ':')
        return Word r
    }) state

let elements = [| 
    parseOperator
    parseCurrencyCode
    parseWord
    parseNumber 
    parsePerCent
|]

let parseElement state =
    (parse {
        do! spaces
        let! r = choice elements
        do! spaces
        return r
    }) state

let parseElements state =
    manyTill parseElement eof state

let parse (input:string) =
    let result = run parseElements input 
    match result with
    | Success (v, _, _) -> v
    | Failure (m, _, _) -> failwith m
票数 5
EN

Stack Overflow用户

发布于 2011-01-11 05:38:02

听起来你真正想要的只是一个雷克萨斯。FSParsec的一个很好的替代方案是FSLex。(不错的入门教程( albiet )有点过时,可以在我的旧博客这里上找到。)使用FSLex,您可以获取输入文本:

代码语言:javascript
复制
XYZ Hotel: 6 nights at 220EUR / night plus 17.5% tax

并将其正确标记为如下所示:

代码语言:javascript
复制
 [ Word("XYZ"); Hotel; Int(6); Word("nights"); Word("at"); Int(220); EUR; ... ]

下一步,一旦您有了一个标记列表,就会执行某种形式的模式匹配/分析来提取语义信息(我认为这就是您真正想要的)。对于规范化的令牌流,它应该非常简单,如:

代码语言:javascript
复制
let rec processTokenList tokens = 
    match tokens with
    | Float(x) :: Keyword("EUR") :: rest  -> // Dollar amount x
    | Word(x) :: Keyword("Hotel") :: rest -> // Hotel x
    | hd :: rest -> // Couldn't find anything interesting...
                    processTokenList rest

那至少能让你开始。但是请注意,随着你的输入得到更多的“正式”,你的词汇也会有用。(如果您只接受非常特定的输入,那么您可以使用适当的解析器并完成它!)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4653820

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档