18

使用数组let foo = [|1;2;3;4|],我可以使用以下任何方法从数组中返回切片。

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

我怎样才能为 List 做同样的事情let foo2 = [1;2;3;4]?当我尝试与我得到的数组相同的语法时error FS00039: The field, constructor or member 'GetSlice' is not defined.

获取 List 的子部分的首选方法是什么?为什么它们不是为支持 GetSlice 而构建的?

4

2 回答 2

43

获取列表子部分的首选方法是什么?为什么不支持 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]
于 2009-12-31T08:22:30.690 回答
10

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

理由在这里

F# 列表类型已经支持索引运算符 xs.[3]。尽管列表是 F# 中的链表,但还是会这样做 - 列表在 F# 中非常常用,以至于在 F# 2.0 中决定支持这一点。

由于支持索引语法,因此也支持 F# 切片语法是有意义的,例如 xs.[3..5]。必须切换到数组类型才能使用切片是非常奇怪的,但您不必为索引进行切换。

尽管如此,朱丽叶回答说,大多数时候分割列表是错误的方法,仍然适用。因此,使用此功能时要明智。

于 2014-12-26T18:23:58.860 回答