为元组添加索引

时间:2016-02-20 08:38:27

标签: haskell

我有一个函数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)...]

我只是个初学者。

3 个答案:

答案 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的列表融合优化功能,您需要使用foldrbuild重写它。虽然某些方面需要修改(重写到/来自),但要点是

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 #-}