我正在尝试创建一个带有列表的函数,如果列表的长度至少为4,则它会反转所述列表的第一个和第二个元素以及最后两个元素.想象一下输入是[1,2,3,4,5,6]这应该给我[2,1,3,4,6,5].
我想弄明白,但这是屁股的痛苦.
所以,这就是我所拥有的:
transf :: [a] -> [a]
transf [] = []
transf xs | length xs >= 4 = ???
| otherwise = xs
Run Code Online (Sandbox Code Playgroud)
所以我认为我可以做一个只能反转那些元素然后在transf函数上调用它的aux函数.有帮助吗?
通常最好使用模式匹配而不是使用length.例如,如果列表具有无限长度,length则将永远循环.所以wen可以定义一个函数:
transf :: [a] -> [a]
transf (a:b:c:d:es) = ...
transf x = x
Run Code Online (Sandbox Code Playgroud)
所以在这里我们定义一个模式(a:b:c:d:es)是定义至少有四个要素(列表模式a,b,c,和d)和列表的其余部分es.
现在,在这种情况下,我们知道我们必须反转列表的前两个元素,因此结果就像b : a : ....现在的问题是我们如何计算列表的其余部分.我们无法添加c和d列表,因为它可能es是空列表,在这种情况下,我们想要反向d和c.这可能导致很多情况.
但是,我们可以在这里使用as-pattern来匹配前两个项目以及列表的其余部分(列表的其余部分应至少包含两个项目).喜欢:
transf :: [a] -> [a]
transf (a:b:cs@(_:_:_)) = b : a : ...
transf x = x
Run Code Online (Sandbox Code Playgroud)
所以现在我们只需要填写....这需要反转最后两项.transf我们可以定义一个新的函数swaplast :: [a] -> [a]来交换最后的项目,而不是让所有的乐趣.如果列表没有两个元素该怎么办可以由我们自己决定,因为我们知道我们将调用该函数的列表将至少有两个元素.例如,我们可以决定只返回空列表和单例列表而不进行修改.所以我们可以实现这样的功能:
swaplast :: [a] -> [a]
swaplast [] = []
swaplast [a, b] = [b, a]
swaplast (a:bs) = a : swaplast bs
Run Code Online (Sandbox Code Playgroud)
那么我们获得实现:
transf :: [a] -> [a]
transf (a:b:cs@(_:_:_)) = b : a : swaplast cs
transf x = x
swaplast :: [a] -> [a]
swaplast [] = []
swaplast [a, b] = [b, a]
swaplast (a:bs) = a : swaplast bs
Run Code Online (Sandbox Code Playgroud)