我有一个函数addIndex [1,2,3] = [(0,1),(1,2),(2,3)]
,它应该为每个对添加一个索引,我在实现它时遇到了麻烦。这就是我所做的;
addIndexs :: [Int] -> [(Int,Int)]
addIndexs [] = []
addIndexs x = zip x [1..length x]
我能够使用zip put实现它我感觉它的作弊,我希望能够在不使用任何预构建函数的情况下实现它。
我没有使用预构建功能的最接近的是
addindex x = [(i,z) | z <- x, i <-[1..length x]]
但是这会为每个元组添加所有索引,所以
addIndex [1,2,3] = [(0,1),(1,1),(2,1),(0,2),(1,2),(2,2)...]
我只是个初学者。
答案 0 :(得分:5)
所以您的问题是如何实施zip
?
取决于你想要处理不同长度列表的方式(Haskell只是忽略了一个更长并且停留在更短的长度),这就是找到正确的模式匹配:
myZip _ [] = []
myZip [] _ = []
myZip (x:xs) (x:ys) = (x,y) : myZip xs ys
(如果你愿意,试着实现这个)
现在您可以轻松地将此操作带到您想要的位置(使用[1..]
作为其中一个列表 - 您不需要length
这种方式在此处和前奏中的工作方式)< / p>
顺便说一句:如果你设法使用列表理解(至少在某种形式下没有zip本身),我会感到惊讶。
虽然这是学习模式匹配和递归的一个很好的练习,但你不会在现实代码中真正做到这一点
你会使用你开始的那个
addIndexs xs = zip [1..] xs
相反 - 请注意,您不需要添加的第一个案例 - 它已包含在内;)
答案 1 :(得分:3)
addIndexs :: [Int] -> [(Int,Int)]
addIndexs [] = []
addIndexs x = myZip x [1..]
myZip :: [a] -> [a] -> [(a,a)]
myZip xs [] = []
myZip [] ys = []
myZip (x:xs) (y:ys) = (x,y) : myZip xs ys
答案 2 :(得分:1)
我建议您使用以下内容:
mapWithIndex :: (Int -> a -> b) -> [a] -> [b]
mapWithIndex = go 0 where
go i f [] = ?
go i f (x : xs) = ?
现在,如果您希望使用GHC的列表融合优化功能,您需要使用foldr
和build
重写它。虽然某些方面需要修改(重写到/来自),但要点是
mapWithIndex f xs = build mi where
mi c n = foldr (\x r !i -> f i x `c` r (i + 1)) n xs 0
{-# INLINE mapWithIndex #-}