如何从haskell列表中提取类似元素的列表

时间:2014-12-10 00:54:33

标签: haskell

给定[1,0,0,0,3,0,0,0,0,2,4,0,0]等列表和索引,如何在Haskell中提取连续的0模式。例如,如果给定索引介于1和3之间,则结果为[0,0,0],如果介于5和8 [0,0,0,0]之间,依此类推

4 个答案:

答案 0 :(得分:1)

首先,构建一个列表,其中为每个数字存储运行长度:

runs :: (Eq a) => [a] -> [(a, Int)]
runs = map (head &&& length) . group

所以,例如

runs [1,0,0,0,1,0,0,0,0,1,1,0,0] == [(1,1),(0,3),(1,1),(0,4),(1,2),(0,2)]

然后,通过以运行长度大小的步骤进行索引来索引此列表:

indexRuns :: Int -> [(a, Int)] -> [a]
indexRuns i [] = error "Index out of bounds"
indexRuns i ((x, l):rs)
  | i < l = replicate l x
  | otherwise = indexRuns (i - l) rs

答案 1 :(得分:0)

这将计算索引周围的零数

numZeros::Int->[Int]->Int
numZeros 0 (1:_) = 0
numZeros i (1:rest) = numZeros (i-1) rest
numZeros i theList
  | i < zeroLen = zeroLen
  | otherwise = numZeros (i-zeroLen) $ drop zeroLen theList
  where
    zeroLen = length (takeWhile (==0) theList)

您可以复制0适当的次数以获得最终列表。

答案 2 :(得分:0)

您可以在O(n)时间内完成此操作:

extract :: Eq a => Int -> [a] -> [a]
extract _ [] = []
extract idx (x:xs) = extract' x [x] 1 xs
  where
    extract' _ _ _ [] = [] -- Index out of bounds
    extract' v vs n (r : rest)
      | idx == n = vs ++ (takeWhile (== v) rest)
      | (v == r) = extract' v (r:vs) (n+1) rest
      | otherwise = extract' r [r] (n+1) rest

答案 3 :(得分:0)

f = f' (takeWhile (== 0)) where
    f' c n    xs  | n < 0 || null xs = []
    f' c n (1:xs) = f (n - 1) xs
    f' c 0    xs  = c xs
    f' c n (0:xs) = f' ((0:) . c) (n - 1) xs

甚至更加模糊

f n xs = g (splitAt n xs) >>= takeWhile (== 0) where
    g (xs, ys@(0:_)) = [reverse xs, ys]
    g          _     = []

一些测试:

main = mapM_ (\i -> print $ (i, f i [1,0,0,0,1,0,0,0,0,1,1,0,0])) [-1..13]

打印

(-1,[])
(0,[])
(1,[0,0,0])
(2,[0,0,0])
(3,[0,0,0])
(4,[])
(5,[0,0,0,0])
(6,[0,0,0,0])
(7,[0,0,0,0])
(8,[0,0,0,0])
(9,[])
(10,[])
(11,[0,0])
(12,[0,0])
(13,[])