在Haskell中获取一个子列表

Pet*_*erM 20 haskell

可能是一个简单的,但我查看了文档并搜索了示例,我仍然不确定答案.

如果我有这样的列表:

[1,2,3,4,5,6,7,8,9,0]
Run Code Online (Sandbox Code Playgroud)

我想提取一个切片,比如从索引4到索引8,即我想要:

[5,6,7,8,9]
Run Code Online (Sandbox Code Playgroud)

在Haskell中这样做的惯用方法是什么?

ibi*_*bid 34

首先,这不是一个数组,它是一个列表.我不是(仅仅)迂腐,因为数组在Haskell中比列表更有问题.

也就是说,一种常见的方式是使用takedrop一起:

Prelude> drop 4 . take 9 $ [1,2,3,4,5,6,7,8,9,0]
[5,6,7,8,9]
Prelude> take (9-4) . drop 4 $ [1,2,3,4,5,6,7,8,9,0]
[5,6,7,8,9]
Run Code Online (Sandbox Code Playgroud)

后者更有效率.

  • 概括:`slice begin end = take(end - begin).放弃开始` - 我也很确定GHC可以优化第一次成功的低效率. (3认同)
  • @ehird,天真地效率会降低,因为每个丢弃的值都会从`take`thunk(额外的比较和增量)计算出来.虽然第二个版本一次完成所有的删除,所以`take`使用普通列表进行操作.显然,如果性能至关重要,则分析是必不可少的.想一想:要获得第一个值,第一个版本需要从`take`获得5,而第二个版本只从`take`获得一个元素.两个版本在`drop`中执行相同数量的工作并计算列表. (3认同)

Dan*_*ton 6

您可能对Data.Vector(slice)感兴趣.

ghci> import Data.Vector
ghci> let v = fromList [1..10]
ghci> v
fromList [1,2,3,4,5,6,7,8,9,10]
ghci> slice 4 5 v
fromList [5,6,7,8,9]
Run Code Online (Sandbox Code Playgroud)

请注意,slicein Data.Vector起始索引切片长度作为输入.


Nom*_*ics 5

> drop 4 (take 9 [1,2,3,4,5,6,7,8,9,0])

[5,6,7,8,9]
Run Code Online (Sandbox Code Playgroud)