我正在尝试实现功能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()
。
答案 0 :(得分:3)
首先,已经有一个针对该应用的应用程序-名为Array.chunkBySize
:
> Array.chunkBySize 2 [|1;2;3;4;5;6;7|]
val it : int [] [] = [|[|1; 2|]; [|3; 4|]; [|5; 6|]; [|7|]|]
Seq
和List
模块中也有类似的功能,因此,如果您的目标是使用字符串,我会考虑使用Seq
变体,因为{{1} }已经实现了string
接口:
seq
但是,如果您对教育而不是GSD感兴趣,那么这里是:
代码的逻辑很好,除了您有一些纯粹的语法错误和一个逻辑。
首先,类型“ a的数组”未表示为> Seq.chunkBySize 2 "abcdefg";;
val it : seq<char []> =
seq [[|'a'; 'b'|]; [|'c'; 'd'|]; [|'e'; 'f'|]; [|'g'|]]
。通常,泛型类型的F#表示法是array 'a
或T<'a>
,例如'a T
或list<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
现在准备好黄金时段了。