数组的子数组列表

时间:2018-09-16 15:45:15

标签: arrays f#

我正在尝试实现功能stride n a,其中n是步长,a是数组。给定像stride 2 [| "a"; "b"; "c"; "d" |]这样的呼叫,它应该返回类似[ [|"a"; "b"|]; [|"c"; "d" |] ]的东西。我是F#的新手,对使用函数语言中的数组一无所知。我知道我写的是垃圾,但这只是一个开始:

let stride n (a : array 'a) =
    let rec r ind =
        if ind >= a.length()
        then
            []
        else 
            a[ind .. (ind + n - 1)]::r(ind + n)
    in
    r 0

(另请参见dotnetfiddle)。这不会编译。我添加了array 'a类型参数,因为编译器找不到length方法,但是似乎不允许这种类型参数。

对于上下文,我试图从字符串中获取字母组,因此我打算将其命名为stride 2 myString.ToCharArray()

1 个答案:

答案 0 :(得分:3)

首先,已经有一个针对该应用的应用程序-名为Array.chunkBySize

> Array.chunkBySize 2 [|1;2;3;4;5;6;7|]
val it : int [] [] = [|[|1; 2|]; [|3; 4|]; [|5; 6|]; [|7|]|]

SeqList模块中也有类似的功能,因此,如果您的目标是使用字符串,我会考虑使用Seq变体,因为{{1} }已经实现了string接口:

seq

但是,如果您对教育而不是GSD感兴趣,那么这里是:

代码的逻辑很好,除了您有一些纯粹的语法错误和一个逻辑。

首先,类型“ a的数组”未表示为> Seq.chunkBySize 2 "abcdefg";; val it : seq<char []> = seq [[|'a'; 'b'|]; [|'c'; 'd'|]; [|'e'; 'f'|]; [|'g'|]] 。通常,泛型类型的F#表示法是array 'aT<'a>,例如'a Tlist<int>。但是,这不适用于数组,因为数组很特殊。有一个int list类型,但是它不是通用类型,因此不能那样使用。取而代之的是,数组的想法已经渗透到CLR中,因此您必须使用特殊的语法System.Array

因此:'a[]而非a : 'a[]

第二,尽管数组确实具有length属性,但将其大写(即a : array 'a),并且它是属性,而不是方法,因此它后面不应有括号。

因此:Length而非a.Length

但是,这不是F#方式。方法和属性都不错,功能也更好。 F#的方式是使用a.length()函数。

因此:Array.length而非Array.length a

奖金:如果这样做,则不需要类型注释a.length(),因为编译器现在可以从: 'a[]的类型中找出它。

第三,对数组,列表以及所有其他具有索引的索引,在左括号之前需要一个点。

因此:Array.length而非a.[ind .. (ind + n - 1)]

第四,在F#中不需要a[ind .. (ind + n - 1)]。您可以忽略它。

使用上述修改,您的程序将运行。 但仅适用于长度为in倍数的数组。在其他所有标签上,您都会得到一个n。这是因为您也有...

逻辑错误是,当您检查IndexOutOfRangeException是否在数组范围之内时,并没有检查ind是否也在数组范围之内。因此,您的分支机构需要第三种情况:

ind + n - 1

现在准备好黄金时段了。