当前位置:  开发笔记 > 编程语言 > 正文

删除元素的函数(如果存在但添加元素)则不会

如何解决《删除元素的函数(如果存在但添加元素)则不会》经验,为你挑选了1个好方法。

我正在寻找一种更简洁的方法来编写一个函数,如果列表不包含它,就会向列表添加元素.或者如果列表确实包含它,则以其他方式删除它,我现在使用一个if子句并且该函数正在运行.

但是我正试图找到一种更好方法来解决这个问题.

这是我的代码:

removeElemOrAdd :: Eq a => a -> [a] -> [a]
removeElemOrAdd elem list = if (List.elem elem list)
                            then (filter(\x -> x /= elem) list)
                            else (elem:list)

Willem Van O.. 5

注:在你的问题一个小不确定性是什么时候做什么x已经发生多次在原始列表倍.我假设这不会发生,如果它发生,只删除第一次出现.意味着removeElemOrAdd 2 [4,2,5,2,7]会导致[4,5,2,7].此外,未指定应添加项目的位置.因为它有一些优点,我选择在列表的末尾执行此操作.

不使用任何库方法的实现如下:

removeElemOrAdd :: Eq a => a -> [a] -> [a]
removeElemOrAdd x (y:ys) | x == y = ys
                         | otherwise = y : removeElemOrAdd x ys
removeElemOrAdd x _ = [x]

或更短的版本:

removeElemOrAdd :: Eq a => a -> [a] -> [a]
removeElemOrAdd x = reoa
    where reoa (y:ys) | x == y = ys
                      | otherwise = y : reoa ys
          reoa _ = [x]

或等效实施(见下面的讨论):

removeElemOrAdd :: Eq a => a -> [a] -> [a]
removeElemOrAdd x = reoa
    where reoa (y:ys) | x == y = ys
                      | otherwise = y : reoa ys
          reoa [] = [x]

该函数的工作原理如下:如果我们讨论的是一个至少包含一个项目的列表(y:ys),我们将进行比较x,y如果它们相等,我们将返回ys:在这种情况下,我们已经删除了元素,我们就完成了.

现在万一这两个不相等,我们返回一个列表构造(:),y因为我们需要保留y并且在尾部,我们将removeElemOrAdd使用x和进行递归调用ys.确实:有可能x在尾部有一个地方ys要删除,而且x如果没有发生,我们仍然需要添加到列表中.

该子句将以递归方式循环遍历列表.从目前发现的y,使得x == y它会删除y.但是,我们可能会到达列表的末尾,但仍然没有找到该元素.在这种情况下,我们将调用最后一个条款.在这里我们知道列表是空的(我们可以写removeElemOrAdd x [])但是为了使函数定义语法总和,我选择使用下划线.如果我们x在列表中找不到,我们只能达到这个状态,所以我们通过返回将它添加到列表的尾部[x].

这种方法优于使用的一个优点if-then-else是,它可以同时执行所有任务(检查,删除和添加),从而提高效率.

另一个优点是,它可以在" 无限 "列表上运行(例如素数列表).列表是懒惰地评估的,所以如果你想取前三项,这个函数只会检查前三项的相等性.



1> Willem Van O..:

注:在你的问题一个小不确定性是什么时候做什么x已经发生多次在原始列表倍.我假设这不会发生,如果它发生,只删除第一次出现.意味着removeElemOrAdd 2 [4,2,5,2,7]会导致[4,5,2,7].此外,未指定应添加项目的位置.因为它有一些优点,我选择在列表的末尾执行此操作.

不使用任何库方法的实现如下:

removeElemOrAdd :: Eq a => a -> [a] -> [a]
removeElemOrAdd x (y:ys) | x == y = ys
                         | otherwise = y : removeElemOrAdd x ys
removeElemOrAdd x _ = [x]

或更短的版本:

removeElemOrAdd :: Eq a => a -> [a] -> [a]
removeElemOrAdd x = reoa
    where reoa (y:ys) | x == y = ys
                      | otherwise = y : reoa ys
          reoa _ = [x]

或等效实施(见下面的讨论):

removeElemOrAdd :: Eq a => a -> [a] -> [a]
removeElemOrAdd x = reoa
    where reoa (y:ys) | x == y = ys
                      | otherwise = y : reoa ys
          reoa [] = [x]

该函数的工作原理如下:如果我们讨论的是一个至少包含一个项目的列表(y:ys),我们将进行比较x,y如果它们相等,我们将返回ys:在这种情况下,我们已经删除了元素,我们就完成了.

现在万一这两个不相等,我们返回一个列表构造(:),y因为我们需要保留y并且在尾部,我们将removeElemOrAdd使用x和进行递归调用ys.确实:有可能x在尾部有一个地方ys要删除,而且x如果没有发生,我们仍然需要添加到列表中.

该子句将以递归方式循环遍历列表.从目前发现的y,使得x == y它会删除y.但是,我们可能会到达列表的末尾,但仍然没有找到该元素.在这种情况下,我们将调用最后一个条款.在这里我们知道列表是空的(我们可以写removeElemOrAdd x [])但是为了使函数定义语法总和,我选择使用下划线.如果我们x在列表中找不到,我们只能达到这个状态,所以我们通过返回将它添加到列表的尾部[x].

这种方法优于使用的一个优点if-then-else是,它可以同时执行所有任务(检查,删除和添加),从而提高效率.

另一个优点是,它可以在" 无限 "列表上运行(例如素数列表).列表是懒惰地评估的,所以如果你想取前三项,这个函数只会检查前三项的相等性.


这种"句法"整体并没有把我视为有价值的东西.第一个模式的保护包括一个`otherwise`子句,列表类型只有两个构造函数,所以在任何情况下覆盖都是显而易见的.如果数据类型的定义可能会发生变化(与列表不同),我宁愿避免使用可能会破坏GHC覆盖检查的通配符.正如我所提到的,在这种情况下,通配符向我发送了警告可能失败的错误信息.
推荐阅读
云聪京初瑞子_617
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有