我的elemIndices函数的结果列表出错

时间:2017-10-18 16:49:35

标签: haskell

该函数实际上有效,但是如果第一个元素等于x,它返回的列表将不是正确的顺序。

功能:

 myelemIndices :: Eq a => a -> [a] -> [Int]
 myelemIndices x [] = [] 
 myelemIndices x l =  if posic n l == x 
                         then myReverse (n : myelemIndices x (init l)) 
                             else myelemIndices x (init l)
         where n = length l - 1

会返回类似的内容:

myelemIndices 1 [1,2,1,2,1]
[2,0,4]

Posic功能等于:

posic :: Int -> [a] -> a
posic 0 (h:t) = h
posic x (a:b) = posic (x-1) b 

myReverse与反向完全相同。我不是在寻找一种有效的功能,只是对我的修正。提前谢谢!

2 个答案:

答案 0 :(得分:2)

每次找到元素时,您都会反转列表。这里的最小变化是使用myElemIndices x (init l) ++ [n]而不是myReverse (n : myelemIndices x (init l))

答案 1 :(得分:2)

代码中的第一个反模式是您使用lengthlength通常会在 O(n) n 列表中的元素数量)中运行,但此外它很麻烦,因为列表可以有无限的长度。在这种情况下,length永远不会终止。在函数式编程中,它有时被视为某些东西可能不正确的标志。

所以第一个问题是:我们需要length吗?您的代码需要做的是返回索引。但是比如说你需要知道电话簿中的哪些页面上列出了“John”的名字,那么你不需要事先知道电话簿有多少页面:你可以简单地看看第一页。如果它有一个名字为John的人,那么你说这是第1页,无论如何,你都会进一步。

我们可以在这里使用相同的方法。我们唯一需要的是一个参数,用于跟踪我们当前正在查看的页面。我们可以通过定义一个将完成大部分工作的 new 函数来引入此参数。所以:

myElemIndices :: Eq a => a -> [a] -> [Int]
myElemIndices x l = go 0 l
    where go = ...

所以我们定义了一个函数go,第一个参数将跟踪页码。如果我们进行递归,我们将需要更新该数字。但是现在我们仍然需要定义go函数。

基本案例很简单:如果我们到达列表末尾(电话簿),我们可以说我们不会再发现任何事件了。所以我们可以写:

go _ [] = []

这意味着,无论页码(_)如何,如果没有页面([]),我们会返回一个空列表作为匹配[]。< / p>

如果我们没有到达电话簿的末尾,我们可以抓取头部h和尾部t。我们必须检查头h是否与查询元素x匹配。万一它,我们返回页码,否则我们不会。无论如何,我们一直在寻找更多页面。所以我们可以写:

go i (h:t) | x == h = i : <next-matches>
           | otherwise = <next-matches>

<next-matches>只是一个递归调用,我们更新页码(i+1),我们继续列表的尾部,所以:

go i (h:t) | x == h = i : tl
           | otherwise = tl
    where tl = go (i+1) t

现在我们可以把它们放在一起:

myElemIndices :: Eq a => a -> [a] -> [Int]
myElemIndices x l = go 0 l
    where go _ [] = []
          go i (h:t) | x == h = i : tl
                     | otherwise = tl
              where tl = go (i+1) t

我们仍然可以改进代码。首先,我们不必写:

myElemIndices x l = go 0 l

请注意,头部和身体都以l结尾。我们可以省略它,并把它变成:

myElemIndices x = go 0

此外,我们也不需要将结果作为Int。只要这些是Num s,我们就可以了。所以我们可以将其概括为:

myElemIndices :: (Eq a, Num n) => a -> [a] -> [n]
myElemIndices x l = go 0 l
    where go _ [] = []
          go i (h:t) | x == h = i : tl
                     | otherwise = tl
              where tl = go (i+1) t