从具有另一个列表中给出的索引的列表元素中提取

时间:2017-06-11 19:47:37

标签: list haskell indexing

所以我需要从给定列表中提取元素,并使用另一个列表中给出的索引。 签名应该是这样的:

search :: [Int] -> [a] -> [a]

和结果

search [1,3,5] [34,65,67,34,23,43,54]
[65,34,43]

据我所知,这里没有标准功能,我可以用更常见的语言进行循环,但是我对haskell不太好。

3 个答案:

答案 0 :(得分:3)

可以使用(!!) :: [a] -> Int -> Int运算符和列表理解来实现这一目标:

search :: [Int] -> [a] -> [a]
search js xs = [xs!!j | j <- js]

但是(!!)运算符在 O(k)中使用 k 所请求的索引,因此这将是低效的。

鉴于索引列表是有序且不超出范围,纯Haskell函数可能如下:

search :: [Int] -> [a] -> [a]
search = search' 0
    where search' _ []     _  = []
          search' i (j:js) xs = y : search' (j+1) js ys
              where (y:ys) = drop (j-i) xs

答案 1 :(得分:3)

假设索引已排序,您可以编写自己的显式递归。

search :: [Int] -> [a] -> [a]
search indices xs = go indices 0 xs  -- start from index 0
   where
   go :: [Int] -> Int -> [a] -> [a]
   -- no more indices, we are done
   go []     _ _                = []
   -- more indices but no more elements -> error
   go _      _ []               = error "index not found"
   -- if the wanted index i is the same as the current index j,
   -- return the current element y, more to the next wanted index
   go (i:is) j yys@(y:_) | i==j = y : go is  j     yys
   -- otherwise, skip y and increment the current index j
   go iis    j (_:ys)           =     go iis (j+1) ys

存在更多高级方法,但这应该是一种基本的有效替代方案。它在O(n)中运行,其中n是列表的长度。

请注意,重复调用!!会需要O(n ^ 2)时间,因为每个!!需要花费O(n)。

如果索引未排序,请改用go (sort indices) 0 xs。成本增加到O(n log n)。

答案 2 :(得分:1)

您可以使用!! operator访问列表元素,如下所示:

List!!index == value_at_that index

因此,您的功能可能如下所示:

search indexes list = [list!!x | x <- indexes]