【问题标题】:Delete list elements by looking on another list通过查看另一个列表来删除列表元素
【发布时间】:2012-12-31 05:01:42
【问题描述】:

我有两个列表。一个列表包含一些随机数据,另一个列表包含需要删除的第一个列表的索引。

例如,让我们考虑两个列表:

let a = [3,4,5,6,6,7,8]
let b = [1,3]

那么,结果输出应该是[3,5,6,7,8]。数字 4 和 6 被删除,因为它们分别位于索引位置 1 和 3。

我是 Haskell 的新手,因此很难找到解决方案。

更新:以下代码使其工作

import Data.List
dele :: Eq a => [a] -> [Int] -> [a]
dele [] _ = []
dele x [] = x
dele x (y:ys) = dele (delete (x !! y) x) ys

我只是想知道,有没有办法通过map/fold方式解决它?

【问题讨论】:

  • 它是一种函数式编程语言,这意味着副作用和可变数据结构已被排除在外!任何解决方案都将涉及使用您想要的项目重新创建部分列表。
  • 问题已更新。通过模式匹配使其现在可以工作。我想知道是否有更好的方法来解决这个问题?
  • 您的解决方案并没有真正奏效。试试dele [1,2,3,4,5,1] [5]
  • @n.m.感谢您的指点 :)

标签: haskell


【解决方案1】:
deleteByIndex :: (Enum a, Eq a, Num a) => [a] -> [b] -> [b]
deleteByIndex r = map snd . filter (\(i, _) -> notElem i r) . zip [0..]

[0..] 产生一个无限列表[0, 1, 2, 3, ...]

zip 用此列表的值和[(0,x), (1, y), ...] 形式的输入列表构造一个对列表

filter 采用函数a -> Bool。 lambda 检查索引(该对的第一个元素)是否在您的输入列表 r 中。

map snd 返回每​​对 zip 列表的第二个元素。

zipfiltermapnotElem 记录在案 here

【讨论】:

  • 输出错误:*Main Data.List> deleteByIndex [1,2,3,4,5,6] [0,3,2]。这给了我一个[0] 的结果列表,但正确的输出列表应该是[2,4,5,6]
【解决方案2】:

在我的头顶:

removeByIndex :: [Integer] -> [a] -> [a]
removeByIndex indices = map snd . filter notInIndices . zip [0..]
    where notInIndices (i,_) = i `notElem` indices

【讨论】:

  • Zounds,被打败了! :D
  • 不错的答案!这就是我的想法:[ x | x <- a , notElem (fromJust $ x ``elemIndex`` a) b](唯一的问题是现在 b 必须让 b= [1, 3] :: [Int])
【解决方案3】:

使用最近受到相当关注的镜头库的替代答案

import Control.Lens
>let a = [3,4,5,6,6,7,8]
>let b = [1,3]
>a^..elements (`notElem`b)
[3,5,6,7,8]

(^..) 只是 toListOf 的中缀,可用于遍历结构并从其部分组成列表。元素功能只是让您选择要包含的元素。

其他选项是 'traverse' 来遍历一个可遍历对象,'both' 来遍历一个 (,) 并且它们与 (.) 组合在一起,因此 traverse.both 将遍历 [(1,2), (3,4)]例如。

[(1,2), (3,4)]^..traverse.both [1,2,3,4]

【讨论】:

    猜你喜欢
    • 2017-12-16
    • 2013-12-19
    • 2022-11-13
    • 2022-11-19
    • 2015-09-20
    • 2013-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多