我需要实现一个带有元素elt
和列表lst
的函数,并返回elt
中第一次出现lst
的位置。
这是我的答案:
elementPosition :: Eq t => t ->[t] -> Int
elementPosition t [] = 0
elmentPosition t lst
| t == head lst = 1
| otherwise = (elementPosition t (tail lst))+1
但是,如果elt
不在lst
,我需要返回0.但此代码将返回lst
的长度。当第一个模式匹配时,我可以做一些事情来返回0
吗?如果没有,我该如何实现这个功能?
答案 0 :(得分:3)
您必须将递归转换为尾部,以便最终决定在堆栈的顶部,而不是在底部。这样你就需要将当前从列表头部累积的距离作为参数传递(当找到匹配时你需要这个距离但如果没有则可以丢弃它)。像
这样的东西elementPosition :: Eq t => t ->[t] -> Int
elementPosition pat lst = elementPosition' 1 pat lst where
elementPosition' _ _ [] = 0
elementPosition' i pat (h:t) | pat == h = i
| otherwise = elementPosition' (i + 1) pat t
但请注意,标准库已经涵盖了它:
import Data.List
elementPosition :: Eq t => t ->[t] -> Int
elementPosition p l = maybe 0 succ $elemIndex p l
答案 1 :(得分:2)
试试这个:
app.UseMvc(routes =>
{
routes.MapRoute( //default
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
routes.MapRoute(
name: "fooid",
template: "{controller=Home}/{action=Index}/{fooid?}");
routes.MapSpaFallbackRoute(
name: "spa-fallback",
defaults: new { controller = "Home", action = "Index" });
});
然后elementPosition :: Eq t => Int -> t -> [t] -> Int
elementPosition _ _ [] = 0
elementPosition pos key (x:xs)
| key == x = pos
| otherwise = elementPosition (pos + 1) key xs
会做你想做的事情
答案 2 :(得分:2)
其他答案讨论如何通过添加累加器来实现此目的。但是,我认为如果没有累加器,如何做到这一点也是很有启发性的;诀窍就是检查递归调用的返回值是否为0
并保持该值而不是递增值(如果是)。所以:
elementPosition :: Eq t => t -> [t] -> Int
elementPosition t [] = 0
elementPosition t lst
| t == head lst = 1
| otherwise = case elementPosition t (tail lst) of
0 -> 0
n -> n+1
答案 3 :(得分:1)
另外,使用zip
(使列表成为元素及其索引元组的列表)和filter
(过滤掉我们要查找的值),我们可以得到这个定义: / p>
elementPosition :: Eq t => t -> [t] -> Int
elementPosition e xs =
case filter ((== e) . fst) xsIndexed of
[] -> 0
(_, i):_ -> i
where xsIndexed = zip xs [1..]
正如@dfeuer所建议的那样,我们可以在单行中得到这个:
import Data.Maybe
elementPosition :: Eq t => t -> [t] -> Int
elementPosition e = maybe 0 fst . listToMaybe . filter ((== e) . snd) . zip [1..]