我正在寻找一种更简洁的方法来编写一个函数,如果列表不包含它,就会向列表添加元素.或者如果列表确实包含它,则以其他方式删除它,我现在使用一个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
是,它可以同时执行所有任务(检查,删除和添加),从而提高效率.
另一个优点是,它可以在" 无限 "列表上运行(例如素数列表).列表是懒惰地评估的,所以如果你想取前三项,这个函数只会检查前三项的相等性.
注:在你的问题一个小不确定性是什么时候做什么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
是,它可以同时执行所有任务(检查,删除和添加),从而提高效率.
另一个优点是,它可以在" 无限 "列表上运行(例如素数列表).列表是懒惰地评估的,所以如果你想取前三项,这个函数只会检查前三项的相等性.