Haskell中如何按年龄对(String, int)类型人员列表排序?
按年龄排序的修改方案
你的现有qsort函数默认按字母顺序排序,是因为Haskell中(String, Int)元组的Ord实例会优先比较第一个元素(姓名),仅当姓名相同时才会对比第二个元素(年龄)。要实现按年龄排序,推荐两种修改方式:
方式1:改成通用排序函数(兼顾多场景)
把qsort调整为接受自定义比较逻辑的版本,既保留原有的按姓名排序功能,也能轻松实现按年龄排序:
-- 支持自定义比较规则的快速排序 qsortBy :: (a -> a -> Bool) -> [a] -> [a] qsortBy _ [] = [] qsortBy _ [x] = [x] qsortBy cmp [x, y] = if cmp x y then [x, y] else [y, x] qsortBy cmp (x:xs) = qsortBy cmp [a | a <- xs, cmp a x || a == x] ++ [x] ++ qsortBy cmp [a | a <- xs, not (cmp a x || a == x)] people = [("Steve",20),("Smith",31),("Kris",19),("Beth",21)] main = do print $ qsortBy (<=) people -- 按姓名字母序排序(原逻辑) print $ qsortBy (\p1 p2 -> snd p1 <= snd p2) people -- 按年龄升序排序
说明:
qsortBy的第一个参数是自定义比较规则:传入两个元素,返回Bool表示前者是否应该排在前面- 按年龄排序时,用
snd p取出元组的第二个元素(年龄),直接对比年龄大小即可
方式2:直接修改排序逻辑(仅针对年龄)
如果只需要按年龄排序,可以直接在原qsort的列表推导中,把比较对象替换为元组的第二个元素:
qsortAge :: [(String, Int)] -> [(String, Int)] qsortAge [] = [] qsortAge [x] = [x] qsortAge [x, y] = if snd x <= snd y then [x, y] else [y, x] qsortAge (x:xs) = qsortAge [a | a <- xs, snd a <= snd x] ++ [x] ++ qsortAge [a | a <- xs, snd a > snd x] people = [("Steve",20),("Smith",31),("Kris",19),("Beth",21)] main = do print $ qsortAge people -- 按年龄升序排序
这种方式更直接,但仅适用于按年龄排序的场景,灵活性不如第一种。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

