基本上,我想创建一个函数,它接受整数列表和另一个列表(此列表可以是任何类型),并生成另一个列表,其中包含“其他列表”中的元素,其间隔由整数列表。如果我输入:
ixs [2,3,1] [3,2,1]
[2,1,3]
到目前为止,我有:
ix :: Int -> [a] -> a
ix a [] = error "Empty list"
ix 1 (x:xs) = x
ix a (x:xs) = ix (a-1) xs
ixs :: [Int] -> [a] -> [a]
ixs [] _ = []
ixs _ [] = []
ixs (x:xs) (y) = ix x y: []
使用此代码我只返回一个值,如下所示:
ixs [1,2] [2,1]
[2]
如何在ix
上重复调用(x:xs)
函数,以便返回我想要的所有值?
编辑:我想在不使用任何标准前奏函数的情况下执行此操作。我只是想使用递归。
答案 0 :(得分:3)
这是(差不多)第二个清单上第一个清单的索引(“获取价值”)的地图
import Data.List ((!!))
-- (!!) :: [a] -> Int -> a
ixs :: [Int] -> [b] -> [b]
ixs ary ixes = map (ary !!) ixes
但是当你按(3 mod 3 = 0)
索引3个元素的列表时,你也有了回绕,所以我们应该只在索引上映射mod
ixs ary ixes = map (ary !!) (map (`mod` length ary) ixes)
然后我们可以简化为“无意义的风格”
ixs ary = map (ary !!) . map (`mod` length ary)
其读取很好地“将索引映射为数组长度,然后将数组索引映射到结果索引”。它给出了正确的结果
> ixs [2,3,1] [3,2,1]
[2,1,3]
要分解前奏函数和Data.List
函数,我们有
(!!) :: [b] -> Int -> b
(x:_) !! 0 = x
(_:xs) !! n
| n > 0 = xs !! (n-1)
| otherwise = error "List.(!!): negative argument."
_ !! _ = error "List.(!!): index too large."
和
map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = f x : map f xs
答案 1 :(得分:0)
也许是这样的
ixs :: [Int] -> [a] -> [a]
ixs idx a = map (`ix` a) idx
您要做的是将索引函数映射到列表中的所有值
索引第二个列表的索引。请注意,您的ix
函数只是!!
函数,但是从1而不是0开始索引。
答案 2 :(得分:0)
您可以颠倒参数的顺序
ix' :: [a] -> Int -> a
ix' [] a = error "Empty list"
ix' (x:xs) 1 = x
ix' (x:xs) a = ix' xs (a-1)
可以更轻松地将ix
映射到indeces列表:
ixs' :: [a] -> [Int] -> [a]
ixs' xs is = map (ix' xs) is
像这样:
> ixs' "Hello Mum" [1,5,6,1,5,6,1,5]
"Ho Ho Ho"
但使用flip
来交换参数会更好 - ix'
只是flip ix
,所以你可以做到
ixs :: [Int] -> [a] -> [a]
ixs is xs = map (flip ix xs) is
然后你打电话给你计划的方式:
> ixs [1,5,6,1,5,6,1,5] "Hello Mum"
"Ho Ho Ho"