给定一个元音列表,我已经编写了函数startsWithVowel来调查一个单词是否以元音开头.正如您所看到的,我将异常用作控制流,这并不理想.如何更好地实现这一点?
let vowel = ['a'; 'e'; 'i'; 'o'; 'u']
let startsWithVowel(str :string) =
try
List.findIndex (fun x -> x = str.[0]) vowel
true
with
| :? System.Collections.Generic.KeyNotFoundException -> false
Run Code Online (Sandbox Code Playgroud)
更新:tx to all:我再次体验:毫不犹豫地问一个新问题.我看到很多非常有用的评论,让他们来吧:-)
Bra*_*nar 11
尝试使用exists方法代替
let vowel = ['a'; 'e'; 'i'; 'o'; 'u']
let startsWithVowel(str :string) = List.exists (fun x -> x = str.[0]) vowel
Run Code Online (Sandbox Code Playgroud)
如果列表中的任何元素对谓词返回true,则exists返回true,否则返回false.
使用集合进行有效查找
let vowels = Set.ofList ['a'; 'e'; 'i'; 'o'; 'u']
let startsWithVowel(str : string) = vowels |> Set.mem (str.[0])
Run Code Online (Sandbox Code Playgroud)
还有另一种选择,tryFindIndex返回Some或None而不是抛出异常:
> let vowel = ['A'; 'E'; 'I'; 'O'; 'U'; 'a'; 'e'; 'i'; 'o'; 'u']
let startsWithVowel(str :string) =
match List.tryFindIndex (fun x -> x = str.[0]) vowel with
| Some(_) -> true
| None -> false;;
val vowel : char list = ['A'; 'E'; 'I'; 'O'; 'U'; 'a'; 'e'; 'i'; 'o'; 'u']
val startsWithVowel : string -> bool
> startsWithVowel "Juliet";;
val it : bool = false
> startsWithVowel "Omaha";;
val it : bool = true
Run Code Online (Sandbox Code Playgroud)
我对这个线程中提到的一些方法进行了基准测试(编辑:添加了第6页).
我填写了一个包含500000个随机单词的列表,并通过各种startsWithVowel函数对其进行过滤,重复10次.
测试代码:
open System.Text.RegularExpressions
let startsWithVowel1 =
let vowels = ['a';'e';'i';'o';'u']
fun (s:string) -> vowels |> List.exists (fun v -> s.[0] = v)
let startsWithVowel2 =
let vowels = ['a';'e';'i';'o';'u'] |> Set.ofList
fun (s:string) -> Set.contains s.[0] vowels
let startsWithVowel3 (s:string) = "aeiou".IndexOf(s.[0]) >= 0
let startsWithVowel4 str = Regex.IsMatch(str, "^[aeiou]")
let startsWithVowel5 =
let rex = new Regex("^[aeiou]",RegexOptions.Compiled)
fun (s:string) -> rex.IsMatch(s)
let startsWithVowel6 (s:string) =
match s.[0] with
| 'a' | 'e' | 'i' | 'o' | 'u' -> true
| _ -> false
//5x10^5 random words
let gibberish =
let R = new System.Random()
let (word:byte[]) = Array.zeroCreate 5
[for _ in 1..500000 ->
new string ([|for _ in 3..R.Next(4)+3 -> char (R.Next(26)+97)|])
]
//f = startsWithVowelX, use #time in F# interactive for the timing
let test f =
for _ in 1..10 do
gibberish |> List.filter f |> ignore
Run Code Online (Sandbox Code Playgroud)
我的拙见:编辑:命令式的IndexOf F#模式比赛赢得速度竞赛.
Set.contains方法赢得了选美比赛.