字符串列表中的不区分大小写匹配

Meh*_*ari 17 string f# case-insensitive pattern-matching match

我正在尝试解析F#应用程序中的命令行参数.我正在使用参数列表上的模式匹配来完成它.就像是:

let rec parseCmdLnArgs = 
  function
  | [] -> { OutputFile = None ; OtherParam = None }
  | "/out" :: fileName :: rest -> let parsedRest = parseCmdLnArgs rest
                                  { OutputFile = Some(fileName) with parsedRest }
Run Code Online (Sandbox Code Playgroud)

问题是我想让"/out"匹配大小写不敏感,同时保留其他东西的情况.这意味着我无法改变输入并匹配输入的小写版本(这将丢失fileName案例信息).

我考虑了几个解决方案:

  • 诉诸when条款并不理想.
  • 每次匹配一个元组,第一个将是实际参数(我将保存以进行进一步处理并将通配符匹配),第二个将是在此类匹配中使用的小写版本.这看起来比第一次更糟.
  • 使用活动模式但看起来过于冗长.我必须ToLower "/out"在每件事之前重复一些事情.

做这些东西有更好的选择/模式吗?我认为这是一个常见的问题,应该有一个很好的方法来处理它.

Tom*_*cek 30

我非常喜欢使用F#活动模式来解决这个问题.它比使用预处理更冗长,但我认为它非常优雅.此外,根据一些BCL指南,ToLower在比较字符串时不应使用(忽略大小写).正确的方法是使用OrdinalIgnoreCase标志.您仍然可以定义一个很好的活动模式来为您执行此操作:

open System

let (|InvariantEqual|_|) (str:string) arg = 
  if String.Compare(str, arg, StringComparison.OrdinalIgnoreCase) = 0
    then Some() else None

match "HellO" with
| InvariantEqual "hello" -> printfn "yep!"
| _ -> printfn "Nop!"    
Run Code Online (Sandbox Code Playgroud)

你是对的,它更加冗长,但它很好地隐藏了逻辑,它给你足够的力量来使用推荐的编码风格(我不确定如何使用预处理来完成).

  • 我发现名称`InvariantEqual`会产生误导,因为你使用的是'OrdinalIgnoreCase`而不是`InvariantCultureIgnoreCase` (2认同)