假设我们有一个电子表格:: [(String,String,Int)]包含 三元组(名称,用户,标记),其中名称是学生,用户的姓氏 是他的用户名,标记是该学生的第一个CW的结果。 编写一个函数sortLastname以字典顺序对电子表格进行排序 使用练习2中定义的高阶插入排序按名称排序。
我的练习2代码:
homerge :: Ord b => (a -> b) -> [a] -> [a] -> [a]
homerge _ xs [] = xs
homerge _ [] ys = ys
homerge fun (x:xs) (y:ys) | fun x < fun y = x : homerge fun xs (y:ys)
| otherwise = y : homerge fun (x:xs) ys`
hoMergeSort :: Ord b => (a -> b) -> [a] -> [a]
hoMergeSort _ [x] = [x]
hoMergeSort fun xs = homerge fun (hoMergeSort fun ys) (hoMergeSort fun ws)
where (ys,ws) = (take l xs, drop l xs)
where l = length xs `div` 2
我当前的尝试:
sortLastName [(x,y,z)] = hoMergeSort ( (x,_,_) (x',_,_) = x<x' ) [(x,y,z)]
我的问题是获取正确的函数来检查3元组的第一个元素是否小于下一个元素。
任何建议将不胜感激。
答案 0 :(得分:0)
让我们不运行。让我们慢慢移动:
-- sortLastName [(x,y,z)] = hoMergeSort ( (x,_,_) (x',_,_) = x<x' ) [(x,y,z)]
sortLastName xyzs = hoMergeSort fun xyzs
where
让我们看一下这个定义,
-- homerge fun (x:xs) (y:ys) | fun x < fun y = x : homerge fun xs (y:ys)
看,我们在那里有fun x
和fun y
?哪些结果作为操作数进入<
比较中?
fun (x,y,z) =
我们要作为操作数进入<
比较中的哪个值?
.....
fun
不用于比较。 由<
在函数homerge
的源代码中完成。 fun
函数用于提供要在该比较中使用的值。
慢慢走,走远。
请注意,这不是字典顺序。这与三元组的第n个字段排序,而与其他字段的值无关。词典顺序是
(x,y,z) < (a,b,c) = x < a || x==a && (y < b || y==b && z < c)
答案 1 :(得分:0)
语法
-- ( (x,_,_) (x',_,_) = x<x' )
不太有效。要创建匿名函数,请使用语法\arg -> result
。如果您要编写以上代码,则结果将是返回x<x'
的另一个函数:
-- \(x,_,_) -> ( \(x',_,_) -> x<x' )
-- i.e. without the parentheses:
-- \(x,_,_) -> \(x',_,_) -> x<x'
正如@WillNess所指出的,您已经在fun x < fun y
的定义内进行了homerge
的比较。
fun
参数应该是从整个元组到要比较的部分的投影。
\(x,_,_) -> x
整个sortLastName函数如下:
sortLastName xyzs = hoMergeSort (\(name,_,_) -> name) xyzs where
如@WillNess所建议的,您可以使用where
语法,该语法对于小型助手定义非常实用:
sortLastName xyzs = hoMergeSort fun xyzs where
fun (name,_,_) = name
请注意,仅通过提供比较,您就不能轻易地颠倒顺序。如果name
字段是Num
,则可以返回0-x
,即\(x,_,_) -> -x
以降序排列,但是对于字符串,没有实际的方法。因此,最好修改hoMergeSort
,使其接受两个参数的比较,而不是期望单个参数的投影。