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



Using Haskell:

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

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

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

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

您可以使用zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]来实现此目的:

zipWith(ix -> if p x then fix else x)[0..]xs

因此,fi(索引(和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,...(。

虽然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

最新更新