根据元素索引修改列表的元素

时间:2017-07-08 09:47:32

标签: list dictionary haskell indexing

使用Haskell:

假设我有清单:[1,3,4,2,3] 我想修改列表中的所有3个。我知道在这种情况下我可以应用它来选择3:

map (\x -> if p x then f x else x) xs 

但是,应用于三位数的函数取决于它们在列表中的索引。

因此,例如,如果将索引添加到所需的数字,我所要求的函数的输出将是:[1,4,4,2,7]

2 个答案:

答案 0 :(得分:7)

您可以使用zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]

zipWith (\i x -> if p x then f i x else x) [0..] xs

其中f因此考虑i(索引)和x(元素)。

例如:

zipWith (\i x -> if x == 3 then (i+x) else x) [0..] xs

生成所需的输出:

Prelude> let xs = [1,3,4,2,3]
Prelude> zipWith (\i x -> if x == 3 then (i+x) else x) [0..] xs
[1,4,4,2,7]

您可以将此逻辑封装到单独的函数中,例如imap :: (Enum n, Num n) => (n -> a -> b) -> [a] -> b

imap :: (Enum n, Num n) => (n -> a -> b) -> [a] -> b
imap = flip zipWith [0..]

这适用于NumEnum的实例的任何类型(所以IntegerIntFloat,...)。

答案 1 :(得分:0)

虽然zipWith可能是正确的方式,但对于各种类型,您可以按照以下方式递归;

tpi :: [Int] -> [Int]
tpi = runner 0
      where runner _ []     = []
            runner n (x:xs) | x == 3    = (n + x) : runner (n+1) xs
                            | otherwise = x : runner (n+1) xs