提问人:sdgfsdh 提问时间:5/29/2020 更新时间:4/5/2021 访问量:255
在 F# 中执行 tryMax 和 tryMin 的最佳方法?
Best way to do tryMax and tryMin in F#?
问:
假设我有一个,如果有任何元素或其他元素,我想返回最大的。F# 似乎没有内置。seq
None
这是我的尝试:
let tryMax xs =
if Seq.isEmpty xs
then
None
else
Seq.max xs |> Some
let tryMin xs =
if Seq.isEmpty xs
then
None
else
Seq.min xs |> Some
- 这种方法有什么问题吗?
- 有没有内置的解决方案?
答:
7赞
Abel
5/29/2020
#1
我认为你的方法总体上是好的。现在删除了一个答案,建议通过捕获空序列的错误来防止对第一项进行双重评估,但这也可能很昂贵。try/with
如果要防止重复计算,可以使用 ,或者根本不使用(使用 或代替)。或者使用 fold,它只迭代一次:Seq.cache
Seq
List
Array
module Seq =
let tryMin sq =
sq
|> Seq.fold(fun x y ->
match x with None -> Some y | Some x -> Some(min x y)) None
用法:
> Seq.tryMin Seq.empty<int>;;
val it : int option = None
> Seq.tryMin (Seq.singleton 2L);;
val it : int64 option = Some 2L
> Seq.tryMin (seq { 2; 3});;
val it : int option = Some 2
> Seq.tryMin (seq { 2; -3});;
val it : int option = Some -3
一种可能更快的方法(我没有计时)是防止在每个最小值或最大值计算结果上创建,同时防止第一项的多次迭代。option
这应该;)要小得多。
module Seq =
let tryMin (sq: seq<_>) =
use e = sq.GetEnumerator()
// this returns false if there is no first item
if e.MoveNext() then
let mutable result = e.Current
while e.MoveNext() do
result <- min e.Current result
Some result
else
None
用法:
> Seq.tryMin Seq.empty<int>;;
val it : int option = None
> Seq.tryMin (Seq.singleton 2L);;
val it : int64 option = Some 2L
> Seq.tryMin (seq { 2; 3});;
val it : int option = Some 2
> Seq.tryMin (seq { 2; -3});;
val it : int option = Some -3
评论
0赞
Bent Tranberg
4/5/2021
这些不是内置的,这很烦人。我想知道是否有添加它们的建议。所有四个。
0赞
Abel
4/7/2021
@BentTranberg,我同意。这里只提到:github.com/fsharp/fslang-suggestions/issues/...,但不是作为添加它的建议。请随时在此处的 F# 建议存储库中创建请求:github.com/fsharp/fslang-suggestions。
2赞
Brian Berns
9/3/2020
#2
FWIW,这里也是:tryMinBy
let tryMinBy projection (items : seq<_>) =
use e = items.GetEnumerator()
if e.MoveNext() then
let mutable minItem = e.Current
let mutable minValue = projection minItem
while e.MoveNext() do
let value = projection e.Current
if value < minValue then
minItem <- e.Current
minValue <- value
Some minItem
else
None
全套:
module Seq
let tryMinBy projection (items : seq<_>) =
use e = items.GetEnumerator ()
if e.MoveNext ()
then
let mutable minItem = e.Current
let mutable minValue = projection minItem
while e.MoveNext () do
let value = projection e.Current
if value < minValue
then
minItem <- e.Current
minValue <- value
Some minItem
else
None
let tryMaxBy projection (items : seq<_>) =
use e = items.GetEnumerator ()
if e.MoveNext ()
then
let mutable maxItem = e.Current
let mutable maxValue = projection maxItem
while e.MoveNext () do
let value = projection e.Current
if value > maxValue
then
maxItem <- e.Current
maxValue <- value
Some maxItem
else
None
let tryMin (items : seq<_>) =
use e = items.GetEnumerator ()
if e.MoveNext ()
then
let mutable minItem = e.Current
while e.MoveNext () do
if e.Current < minItem
then
minItem <- e.Current
Some minItem
else
None
let tryMax (items : seq<_>) =
use e = items.GetEnumerator ()
if e.MoveNext ()
then
let mutable maxItem = e.Current
while e.MoveNext () do
if e.Current > maxItem
then
maxItem <- e.Current
Some maxItem
else
None
评论
0赞
Abel
4/7/2021
我很欣赏在下面扩展我的原始答案,您可以在其中找到这种方法的解释和用法以及替代方案。虽然我建议使用内置函数,因为它们可能更好地内联/优化并增加可读性。min
max
评论