给定从-273到5526的列表int,我想将最接近的整数打印到零。如果你有平等(n和-n),我们应该采用n。
let temps = // this contains => 1 -2 -8 4 5
let (|Greater|_|) a b = if a > b then Some() else None
let (|Smaller|_|) a b = if a < b then Some() else None
let compareTemperatures a b =
let distanceA = abs a
let distanceB = abs b
match distanceA with
| Greater distanceB -> b
| Smaller distanceB -> a
| _ -> abs a
printfn "%i" (temps |> Seq.reduce compareTemperatures)
然后返回-8而不是1.这对我来说似乎是正确的,我找不到错误,但我是F#的新手,所以我可能在任何地方都犯了错误,看不到它:(
提前致谢
答案 0 :(得分:10)
我认为你的比较是错误的 - 当你写:
match distanceA with
| Greater distanceB -> b
| Smaller distanceB -> a
然后distanceA
作为第二个参数传递给Greater
,因此如果b
远离零,您将返回b
(在第一种情况下) 。以下内容将使其有效:
match distanceA with
| Greater distanceB -> a
| Smaller distanceB -> b
也就是说,使用活动模式只会使代码变得不必要地复杂化(并且很容易引入像这样的错误)。以下内容相同,易于理解,也更简单:
let compareTemperatures a b =
if abs a > abs b then b else a
temps |> Seq.reduce compareTemperatures
我认为这里的教训是模式匹配对于代数数据类型和选项值等问题非常有效,但对于if
工作正常的简单数值比较而言,它并不是很有用!
答案 1 :(得分:2)
因此,您希望比较值,首先使用绝对值,然后使用符号。这是我的单行:
temps |> Seq.minBy (fun x -> abs x, -sign x)
测试用例(打印2
):
let li = [-2; 2; -2; 3; -5]
li |> Seq.minBy (fun x -> abs x, -sign x) |> printfn "%d"
答案 2 :(得分:1)
这应该是对Thomas回答的评论,但我对移动应用来说太愚蠢了......
if abs (2*a-1) > abs (2*b) then b else a
怎么样?