我正在尝试使用fold或foldBack对数组进行排序。
我试过这样做:
docker-compose -f docker-compose.prod.yml up --build --no-deps -d SERVICE
这个错误的错误很可怕。如果这是一个列表,那么我将知道如何通过递归函数实现这一点,但事实并非如此。
因此,如果有人能够告诉我如何给予折叠或折返的可行功能,那么我将是创造性的。
在开始使用let arraySort anArray =
Array.fold (fun acc elem -> if acc >= elem then acc.append elem else elem.append acc) [||] anArray
进行建议之前,这不会发生,因为这是学校作业,因此不允许。
答案 0 :(得分:3)
我们可以将Array.fold
用于简单的类似插入排序的算法:
let sort array =
let insert array x =
let lesser, greater = Array.partition (fun y -> y < x) array
[| yield! lesser; yield x; yield! greater |]
Array.fold insert [||] array
我认为这与你的尝试最接近。
你必须返回相同数组的排序版本的注释在这里有点令人困惑 - 默认情况下F#是不可变的,因此以这种方式使用Array.fold
实际上会创建一个新数组,保持原始数据不变。这与您将其转换为列表,对其进行排序,然后转换回来的情况大致相同。在F#中,数组类型是不可变的,但数组的元素都是可变的。这意味着你可以进行真正的就地排序(例如通过库函数Array.sortInPlace
),但我们不经常在F#中这样做,而是支持默认的Array.sort
,返回一个新数组。
您的尝试存在一些问题,这就是您遇到一些错误的原因。
首先,附加数组的操作与您尝试的操作非常不同。我们可以使用yield
语法通过[| yield! array ; yield element |]
附加到数组,如果它是数组(或实际上是任何yield!
),我们使用IEnumerable
,{ {1}}如果它是单个元素。
其次,您无法将数组类型与数组元素进行比较。这是一个类型错误,因为yield
需要两个相同类型的参数,并且您尝试为其提供compare
和'T
。它们可以是相同的类型,也可以是无限的('T array
所以'T = 'T array
等等。你需要找出你应该比较的东西。
第三,即使您可以将数组与元素进行比较,也会出现逻辑问题。你的元素要么在最后,要么在开头就是正确的。如果它大于第一个元素但小于最后一个元素会怎样?
最后一点,你仍然可以在数组上使用递归和模式匹配,它不像列表那样整洁,因为你不能做经典的'T array = 'T array array
技巧。这是一个基本的(不那么)快速实施方案。
| head :: tail ->
这里的速度可能比let rec qsort = function
| [||] -> [||]
| arr ->
let pivot = Array.head arr
let less, more = Array.partition (fun x -> x < pivot) (Array.tail arr)
[| yield! qsort less ; yield pivot ; yield! qsort more |]
慢几个数量级,因为我们必须以这种方式创建许多数组,而.NET的Array.sort
方法却没有。