F#使用foldBack或fold折叠数组。

时间:2016-10-12 10:58:40

标签: arrays sorting f# append fold

我正在尝试使用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 进行建议之前,这不会发生,因为这是学校作业,因此不允许。

1 个答案:

答案 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方法却没有。