我是Haskell编程的新手,我尝试通过/不使用列表推导来解决问题。
问题是在列表中查找元素的索引并返回索引列表(在列表中找到元素的位置)。
我已经通过使用列表推导解决了问题,但是现在我有一些不使用列表推导来解决问题的问题。
以我的递归方式:
我尝试将[0..(length list)]
和的列表压缩为自己。然后,如果元素a等于列表中的元素->用压缩的Tupel的第一个元素创建一个新列表,然后list(my index)
以递归方式搜索该函数,直到列表为[]。
这就是我的列表理解(有效):
positions :: Eq a => a -> [a] -> [Int]
positions a list = [x | (x,y) <- zip [0..(length list)] list, a == y]
那是我的递归方式(不起作用):
positions' :: Eq a => a -> [a] -> [Int]
positions' _ [] = []
positions' a (x:xs) =
let ((n,m):ns) = zip [0..(length (x:xs))] (x:xs)
in if (a == m) then n:(positions' a xs)
else (positions' a xs)
*对不起,我不知道如何突出显示单词
但是ghci说:
*Main> positions' 2 [1,2,3,4,5,6,7,8,8,9,2]
[0,0]
它应该是这样(我的列表理解):
*Main> positions 2 [1,2,3,4,5,6,7,8,8,9,2]
[1,10]
我的错误在哪里?
您尝试的问题只是当您说:
let ((n,m):ns) = zip [0..(length (x:xs))] (x:xs)
然后n
永远是0
。这是因为您要(n,m)
与的第一个元素进行匹配,该元素zip [0..(length (x:xs))] (x:xs)
必须始终为(0,x)
。
这本身不是问题,但是这确实意味着您必须正确处理递归步骤。你有它的方式,现在,positions _ _
如果非空,将始终有0
它的第一要素,因为你允许它找到一个匹配的唯一方法是,如果它在列表的头部,导致的一个指标0
。这意味着您的结果将始终是正确长度的列表,但包含所有元素0
-如您所见。
问题不在于您的递归方案,而是与您不修改结果以说明您不总是希望0
将其添加到结果列表的开头有关。由于每个递归调用仅向要查找的索引加1,因此您要做的就是递归结果上map
的增量函数(+1)
:
positions' :: Eq a => a -> [a] -> [Int]
positions' _ [] = []
positions' a (x:xs) =
let ((0,m):ns) = zip [0..(length (x:xs))] (x:xs)
in if (a == m) then 0:(map (+1) (positions' a xs))
else (map (+1) (positions' a xs))
(请注意,我已将您更改let
为n
始终是显式的0
-我宁愿以这种方式进行显式更改,但这本身不会更改输出。)由于m
始终绑定x
且ns
根本没有使用,我们可以取消let,插入以下内容的定义m
:
positions' :: Eq a => a -> [a] -> [Int]
positions' _ [] = []
positions' a (x:xs) =
if a == x
then 0 : map (+1) (positions' a xs)
else map (+1) (positions' a xs)
如果愿意,可以继续排除重复的因素map (+1) (positions' a xs)
。
顺便说一句,您不需要显式递归来避免此处的列表理解。其一,列表内涵基本上都是针对的用途的替代map
和filter
。我本来要明确地写出来,但是我看到@WillemVanOnsem给出了这个答案,所以我将简单地介绍给他。
另一种方式,尽管如果要求您自己实现这一点也许不可接受,但是将仅使用内置的elemIndices函数,该函数正是您要在此处实现的功能。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句