2009-12-31 86 views
15

使用数组​​我可以使用以下任意一种方法从数组中返回切片。F#中列表中的切片功能#

foo.[..2] 
foo.[1..2] 
foo.[2..] 

我该如何为列表let foo2 = [1;2;3;4]做同样的事情?当我尝试使用与我获得的阵列相同的语法时error FS00039: The field, constructor or member 'GetSlice' is not defined.

获取列表的子部分的首选方法是什么,以及为什么不构建它们以支持GetSlice?

回答

36

什么是越来越 列表的分段的首选方法,为什么不 内置支持GetSlice?

让我们把最后一个问题第一个和最后的第一个问题:

为什么列表不支持GetSlice

列表实现为链表,所以我们没有有效的索引访问他们。相对而言,foo.[|m..n|]需要O(n-m)时间阵列,等效语法需要O(n)时间的列表。这是一个很大的问题,因为它阻止我们在绝大多数有用的情况下有效地使用切片语法。

例如,我们可以切开一数组大小相同的条线时间:

let foo = [|1 .. 100|] 
let size = 4 
let fuz = [|for a in 0 .. size .. 100 do yield foo.[a..a+size] |] 

但是,如果我们使用什么列表,而不是?每次致电foo.[a..a+size]需要更长,更长,整个操作是O(n^2),使其非常不适合这项工作。

大多数情况下,切片清单是错误的方法。我们通常使用模式匹配来遍历和操作列表。

切片清单的首选方法?

尽可能使用模式匹配,如果可以的话。否则,你可以依傍Seq.skipSeq.take削减了名单和顺序为您提供:

> [1 .. 10] |> Seq.skip 3 |> Seq.take 5 |> Seq.toList;; 
val it : int list = [4; 5; 6; 7; 8] 
8

F#4.0将允许列表(link)切片的语法。

理由是here

的F#的列表类型已经支持的索引操作符,XS [3]。尽管事实上列表是F#中的链接列表,但F#中的列表在F#中的使用非常普遍,因此在F#2.0中决定支持此列表。

由于支持索引语法,因此也支持F#切片语法(例如, [3..5] XS。切换到数组类型以使用切片是非常奇怪的,但是您不必为索引创建切换。

尽管如此,朱丽叶回答说,大部分时间切分清单是错误的方法,但仍然如此。所以使用这个功能时要明智。