获取Haskell中字符串列表中元素的位置

时间:2016-01-03 18:30:19

标签: haskell

我的头衔可能有些偏差,我会尝试更好地解释一下我想要实现的目标。

基本上我要说我有一个清单:

["1234x4","253x4",2839",2845"]

现在我想将包含元素5的字符串的所有位置添加到新列表中。在当前示例中,结果列表将是:

[1,3]

为此我已经为elem完成了类似的功能:

myElem [] _ = False
myElem [x] number =
  if (firstCheck x) then if digitToInt(x) == number then True else False else False
myElem (x:xs) number =
if (firstCheck x) then (if digitToInt(x) == number then True else myElem xs number) else myElem xs number

其中firstCheck x检查checked元素不是'x'或'#'

现在在我当前的函数中,我获得了包含元素的第一个元素位置,但是我的头部仍然在如何获取完整列表:

findBlock (x:xs) number arv =
  if myElem x number then arv else findBlock xs number arv+1

arv为0且number是我正在寻找的数字。

例如输入:

findBlock ["1234x4","253x4",2839",2845"] 5 0 

结果将是1

任何帮助都将不胜感激。

3 个答案:

答案 0 :(得分:7)

您想要的功能已存在于Data.List模块中,名称为findIndices。您只需使用(elem '5')作为谓词。

http://hackage.haskell.org/package/base-4.8.1.0/docs/Data-List.html#v:findIndices

如果由于某种原因,你不允许使用内置的,它会有一个非常漂亮的定义(虽然实际使用的那个有一个更复杂,更有效的一个):

findIndices p xs = [ i | (x,i) <- zip xs [0..], p x]

顺便说一句,我通过在Hoogle中搜索[a] -> (a -> Bool) -> [Int]类型找到了这个函数,其中(模数参数排序)显然是函数必须具有的类型。找出Haskell的最佳方法是考虑它需要的类型并搜索Hoogle或Hayoo的类型。 Hoogle是更好的IMO,因为它在类型上略有模糊匹配;例如Hayoo不会通过我给出的类型在这里找到函数,因为它以相反的顺序接受参数。

答案 1 :(得分:3)

findIndices的实现,用于教学目的:

findIndices ok list = f list 0 where
  f [] _ = []
  f (x:xs) ix
    | ok x      = ix : f xs (ix+1)
    | otherwise =      f xs (ix+1)

findIndices (elem '5') my_list_o_strings

一样使用它

答案 2 :(得分:1)

您正试图通过列表工作,跟踪您在列表中的位置。这样做最简单的功能是

mapWithIndex :: (Int -> a -> b) -> [a] -> [b]
mapWithIndex = mwi 0 where
  mwi i _f [] = i `seq` []
  mwi i f (x:xs) = i `seq` f i x : mwi (i+1) f xs

这需要一个函数和一个列表,并将该函数应用于每个索引和元素。所以

mapWithIndex (\i x -> (i, x)) ['a', 'b', 'c'] =
[(0,'a'), (1,'b'),(2,'c')]

完成后,您可以filter列表获得您想要的对:

filter (elem '5' . snd)

然后map fst覆盖它以获取索引列表。

更综合的方法是使用foldrWithIndex

foldrWithIndex :: (Int -> a -> b -> b) -> b -> [a] -> b
foldrWithIndex = fis 0 where
  fis i _c n [] = i `seq` n
  fis i c n (x:xs) = i `seq` c i x (fis (i+1) c n xs)

这使您可以一步完成所有事情。

事实证明,您可以非常巧妙地使用foldrWithIndex实施foldr,这使得它可用于任何Foldable容器:

foldrWithIndex :: (Foldable f, Integral i) =>
  (i -> a -> b -> b) -> b -> f a -> b
foldrWithIndex c n xs = foldr go (`seq` n) xs 0 where
  go x r i = i `seq` c i x (r (i + 1))

反正

findIndices p = foldrWithIndex go [] where
  go i x r | p x = i : r
           | otherwise = r