我必须编写一个函数,如果给定列表按升序排序,则返回true。空元素和单元素列表已排序。此外,[5,12,12]应该返回true。
我写了一个似乎有效的功能:
let rec isSorted (l: int list) =
match l with
| [] -> true
| [x] -> true
| [x;y] -> x <= y
| x::y::xr -> if x > y then false else isSorted([y] @ xr);
但它似乎有点偏离......我在想有必要有一个更简单的方法吗?我讨厌我必须匹配4个案例,但我无法弄清楚如何让它变得更聪明。
有更好的解决方案吗?
答案 0 :(得分:14)
您可以组合现有功能:
let isAscending l = l |> Seq.pairwise |> Seq.forall (fun (a, b) -> a <= b)
printfn "%b" (isAscending []) // true
printfn "%b" (isAscending [1]) // true
printfn "%b" (isAscending [5;12]) // true
printfn "%b" (isAscending [5;12;12]) // true
printfn "%b" (isAscending [5;12;12;11]) // false
答案 1 :(得分:7)
好吧,永远不要说
[y] @ xr
当
y :: xr
也会这样做。 (一般来说,@
是一种代码气味。)
有点挑剔,但最后一行可能是
| x::((y::_)as t) -> if x > y then false else isSorted(t)
并避免进行任何分配。
现在,你需要第三种情况吗?如果删除它会发生什么?
答案 2 :(得分:5)
回到原始代码(而不是建议的库调用),我会说你可以做一些改进:
y::xr
再次与[y] @ xr
(或y::xr
)拼接在一起是不正确的。 as
表达似乎更好。 if..then
看起来有点不合适。我提出了以下修订版本:
let rec isSorted l =
match l with
| [] | [_] -> true
| h1::(h2::_ as tail) -> h1 <= h2 && isSorted tail
我怀疑它比原版更有效,但它更容易看到。
答案 3 :(得分:2)
这在效率方面是一个特别糟糕的解决方案,所以我永远不会在现实世界中使用它,但这是一个非常实用的方式来查看我在博客示例中提出的问题:
让isSorted l = l =(l |&gt; List.sort)