【问题标题】:Extract from a list elements with indexes given in another list从另一个列表中给定索引的列表元素中提取
【发布时间】:2017-06-11 19:47:36
【问题描述】:

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

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

结果

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

据我所知,这没有标准函数,我可以在更常见的带有循环的语言上做到这一点,但我对 haskell 不太擅长。

【问题讨论】:

    标签: list haskell indexing


    【解决方案1】:

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

    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】:

    可以使用(!!) :: [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
    

    【讨论】:

    • 第二版函数不编译,类型不匹配。
    • @Agent_0f_things:忘记了口音。现已修复。
    【解决方案3】:

    您可以像这样使用!! operator 访问列表的元素:

    List!!index == value_at_that index
    

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

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

    【讨论】:

    • 正确,但是我想说这相当效率低下。列表查找为 O (n),应避免重复使用 !!
    • @leftaroundabout,嗯,是的,但是考虑到索引的顺序似乎没有限制,如果只给出这些元素的索引,那么如何从列表中提取元素呢?如果有一些,那么可以进行改进。
    • 排序只是 O (n · log n),所以对于足够大的列表来说,O i>强加一个升序(但也保留原始顺序的信息),然后使用它来提取元素,然后重新排序为请求索引的原始顺序。
    • ...或者,您还可以将列表转换为对索引更友好的结构(VectorIntMap)并从中查找索引,而不是值列表本身.
    • 我知道!! 操作员只是想不通如何在这里正确使用它。据我所知,索引总是按升序排列,但是可以说存在“差距”。他们不应该越界。
    猜你喜欢
    • 1970-01-01
    • 2018-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多