我有一个字符串长度列表,我想从它们中获取跨度索引。所以给定长度[23, 27, 47]我想产生[(0, 23), (24, 27), (28, 47)]。我怎样才能做到这一点?

到目前为止,这就是我所拥有的。我不确定自己走的路是否正确:

makeSpans :: [Int] -> [(Int, Int)]
makeSpans [x:y:xs] = [(x+1, y), makeSpans xs]
makeSpans [x:y] = (x+1, y)
makeSpans y = y

最佳答案

这是您想要的一个小例子:

> let list = ["abc", "abc", "abc"]
> import Control.Arrow
> fmap (second pred) $ zip <*> tail $ scanl (\acc x -> acc + length x) 0 list
> [(0,2),(3,5),(6,8)]

细分为:
  • scanl列表,将每个单词的长度添加到累加器
  • 为每个列表项及其后续项创建对:
  • > zip <$> tail $ [0,3,6,9]
    > [(0,3),(3,6),(6,9)]
    
  • 使用second映射到每对的第二个元素上,以固定对,使其不重叠(pred等效于(-)1)。

  • 对我而言,这种解决方案比从头开始编写递归函数更容易构建。另外,它读起来就像管道,因此无需跟踪多个级别的间接和令人难以置信的递归。

    10-06 13:11