2

基本上,我想创建一个函数,该函数接受一个整数列表和另一个列表(该列表可以是任何类型),并以整数列表指定的间隔生成另一个列表,其中包含“其他列表”中的元素. 如果我输入:

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)以使其返回我想要的所有值?

编辑:我想在不使用任何标准前奏函数的情况下做到这一点。我只想使用递归。

4

3 回答 3

3

这(几乎)是第一个列表在第二个列表上的索引(“获取值”)的映射

import Data.List ((!!))
-- (!!) :: [a] -> Int -> a

ixs :: [Int] -> [b] -> [b]
ixs ary ixes = map (ary !!) ixes

但是当你索引一个 3 元素列表时,你也有环绕(3 mod 3 = 0),所以我们应该只映射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]

为了分解 Prelude 函数和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
于 2013-07-05T17:36:29.647 回答
0

也许像这样

ixs :: [Int] -> [a] -> [a]
ixs idx a = map (`ix` a) idx

您要做的是将索引函数映射到索引列表中的所有值以索引第二个列表。请注意,您的ix函数只是!!函数,但从 1 而不是 0 开始索引。

于 2013-07-05T17:33:54.963 回答
0

你可以颠倒参数的顺序

ix' :: [a] -> Int -> a
ix' [] a = error "Empty list"
ix' (x:xs) 1 = x
ix' (x:xs) a = ix' xs (a-1)

为了更容易映射ix索引列表:

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'is just 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"
于 2013-07-05T17:38:43.893 回答