我想对列表的前三个元素进行排序,而其他元素保持不变。而且我不想使用任何库函数,因为我是Haskell的新手。
这是我到目前为止所拥有的:
{-# OPTIONS_GHC -Wincomplete-patterns #-}
sort2 (x, y) = if x > y then (y,x) else (x,y)
sort3 (x,y,z)
| x > y && y > z = (z,y,x)
| x > z && z > y = (y,z,x)
| y > x && x > z = (z,x,y)
| y > z && z > x = (x,z,y)
| z > x && x > y = (y,x,z)
| z > y && y > x = (x,y,z)
| otherwise = (0,0,0)
--sortfirst3 :: [Int] -> [Int]
sortfirst3 (x:y:z:v:xs) = sort3(x,y,z) : sortfirst3 (v:xs)
我正在尝试对前三个元素进行排序,将它们放在列表中,然后将其他元素放在另一个列表中,然后将它们彼此串联。但是,由于类型差异元组和列表,这会产生错误。我应该有另一种方法吗?
答案 0 :(得分:6)
您不需要涉及元组。您可以将为元组编写的内容写为匹配的模式。
sortFirst3 [x, y] = if x > y then [y, x] else [x, y]
sortFirst3 [x, y, z]
| x >= y && y >= z = [z, y, x]
| x >= z && z >= y = [y, z, x]
| y >= x && x >= z = [z, x, y]
| y >= z && z >= x = [x, z, y]
| z >= x && x >= y = [y, x, z]
| z >= y && y >= x = [x, y, z]
sortFirst3 (x : y : z : ws) = sortFirst3 [x, y, z] ++ ws
sortFirst3 xs = xs
最后一行捕获未匹配的内容,即单例和空列表,它们在排序时保持不变。由于元素可能重复出现,因此您在警卫中不应有严格的不平等。还要注意,在您的代码中,即使您没有类型不匹配,对sortFirst3
的递归调用也将是错误的,因为对前三个术语进行排序后,其余的前三个将被排序,等等。
答案 1 :(得分:0)
sortfirst3 (x:y:z:v:xs) = sort3(x,y,z) : sortfirst3 (v:xs)
此定义表示,将列表中的前4个元素从列表中删除,将前3个元素排序为一个元组,然后将其与列表的其余部分一起包含在列表的第四个元素的(递归)结果上。
这揭示了要进行的三个更改。
首先,我们只需要匹配前3个元素,而不是前4个元素,但是我们也应该处理列表<3个元素长的情况。我刚把它弄错了,但是你可以使用例如。改为sort2
。
sortfirst3 (x:y:z:xs) = sort3 (x,y,z) : sortfirst3 xs
sortfirst3 _ = error "Can't sort first 3 elements of list shorter than 3 elements"
第二,我们打算对前三个元素进行排序。生成一个3元素列表。 (:) :: a -> [a] -> [a]
,即。在第一个参数中接受一个元素(而不是列表),我们想要的是连接(++) :: [a] -> [a] -> [a]
。
sortfirst3 (x:y:z:xs) = sort3 (x,y,z) ++ sortfirst3 xs
第三,我们打算不影响前三个元素,因此我们实际上不应该对列表的其余部分进行递归调用-否则,我们将列表按3个元素块排序。
sortfirst3 (x:y:z:xs) = sort3 (x,y,z) ++ xs
现在这几乎是正确的,但是对于sort3
来说,如您所标识的那样,它会返回一个元组而不是一个三元素列表。 kuoytfouy的答案对此有所帮助。