像F#中的List一样切片

时间:2009-12-31 07:39:22

标签: list f# slice

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

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

如何为列表let foo2 = [1;2;3;4]执行相同的操作?当我尝试与数组相同的语法时,我得到error FS00039: The field, constructor or member 'GetSlice' is not defined.

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

2 个答案:

答案 0 :(得分:40)

  

获得的首选方法是什么   列表的一个小节,为什么不是   为支持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]

答案 1 :(得分:8)

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

理由是here

  

F#列表类型已经支持索引运算符xs。[3]。尽管列表是F#中的链表,但这已经完成了 - 列表在F#中非常常用,在F#2.0中它决定支持这一点。

     

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

仍然,朱丽叶回答说,大多数时候切片列表是错误的方法,仍然是正确的。因此,使用此功能时要明智。