从 F# 中的列表中提取单个元素
我想从 F# 的序列中提取单个项目,或者如果没有或多个则给出错误。 做这个的最好方式是什么?
我目前
let element = data |> (Seq.filter (function | RawXml.Property (x) -> false | _ -> true))
|> List.of_seq
|> (function head :: [] -> head | head :: tail -> failwith("Too many elements.") | [] -> failwith("Empty sequence"))
|> (fun x -> match x with MyElement (data) -> x | _ -> failwith("Bad element."))
似乎可行,但这真的是最好的方法吗?
编辑:当我被指向正确的方向时,我想到了以下内容:
let element = data |> (Seq.filter (function | RawXml.Property (x) -> false | _ -> true))
|> (fun s -> if Seq.length s <> 1 then failwith("The sequence must have exactly one item") else s)
|> Seq.hd
|> (fun x -> match x with MyElement (_) -> x | _ -> failwith("Bad element."))
我想它更好一点。
I want to extract a single item from a sequence in F#, or give an error if there is none or more than one. What is the best way to do this?
I currently have
let element = data |> (Seq.filter (function | RawXml.Property (x) -> false | _ -> true))
|> List.of_seq
|> (function head :: [] -> head | head :: tail -> failwith("Too many elements.") | [] -> failwith("Empty sequence"))
|> (fun x -> match x with MyElement (data) -> x | _ -> failwith("Bad element."))
It seems to work, but is it really the best way?
Edit: As I was pointed in the right direction, I came up with the following:
let element = data |> (Seq.filter (function | RawXml.Property (x) -> false | _ -> true))
|> (fun s -> if Seq.length s <> 1 then failwith("The sequence must have exactly one item") else s)
|> Seq.hd
|> (fun x -> match x with MyElement (_) -> x | _ -> failwith("Bad element."))
I guess it's a little nicer.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
序列有查找功能。
但如果你想确保seq只有一个元素,那么做一个Seq.filter,然后取filter后的长度并确保它等于1,然后取头。 全部在Seq中,无需转换为列表。
编辑:
顺便说一句,我打算建议检查结果的尾部是否为空(O(1)),而不是使用函数
length (O(n)).Tail 不是 seq 的一部分,但我认为您可以找到一种模拟该功能的好方法。
Sequence has a find function.
but if you want to ensure that the seq has only one element, then doing a Seq.filter, then take the length after filter and ensure it equals one, and then take the head. All in Seq, no need to convert to a list.
Edit:
On a side note, I was going to suggest checking that the tail of a result is empty (O(1), instead of using the function
length
(O(n)). Tail isn't a part of seq, but I think you can work out a good way to emulate that functionality.以现有序列标准函数的风格完成
您可以做一个纯粹的实现,但它最终会跳过圈子以确保正确和高效(在第二场比赛中快速终止实际上需要一个标志说“我已经找到了它”)
done in the style of the existing sequence standard functions
You could do a pure implementation but it will end up jumping through hoops to be correct and efficient (terminating quickly on the second match really calls for a flag saying 'I found it already')
更新的答案是使用 Seq.exactlyOne ,它会引发 ArgumentException
Updated answer would be to use Seq.exactlyOne which raises an ArgumentException
使用现有的库函数有什么问题吗?
What's wrong with using the existing library function?
用这个:
Use this:
我的两分钱...这适用于选项类型,所以我可以在我的自定义也许 monad 中使用它。 可以很容易地修改,但可以使用异常
My two cents... this works with the option type so I can use it in my custom maybe monad. could be modified very easy though to work with exceptions instead