Haskell中不使用groupBy,仅用sort/sortBy实现排序去重
不用groupBy实现排序去重的方案
当然可行,我们可以先通过sort或sortBy完成排序,再手动遍历排序后的列表过滤重复元素,完全不需要groupBy。
基础实现:用sort+递归去重
先利用sort对列表进行默认排序(依赖Ord类型约束),再通过递归遍历跳过与前一个元素相同的项:
import Data.List (sort) cData :: [String] cData = ["Blue", "Red", "Yellow", "Blue", "Yellow", "Blue", "Yellow", "Red", "Blue"] uniqueColours :: Ord a => [a] -> [a] uniqueColours = go . sort where go [] = [] go [x] = [x] go (x:y:rest) | x == y = go (y:rest) | otherwise = x : go (y:rest) -- 测试:uniqueColours cData 会返回 ["Blue","Red","Yellow"]
结合sortBy的实现(展示自定义排序逻辑)
sortBy的作用是允许你传入自定义的比较函数(类型为a -> a -> Ordering),而非使用默认的Ord比较规则。比如如果我们想按字符串长度排序后再去重,就可以用sortBy自定义排序逻辑:
import Data.List (sortBy) import Data.Ord (comparing) -- 按字符串长度排序,长度相同则用默认字符串比较 lengthThenLex :: String -> String -> Ordering lengthThenLex = comparing length <> compare uniqueColoursByLength :: [String] -> [String] uniqueColoursByLength = go . sortBy lengthThenLex where go [] = [] go [x] = [x] go (x:y:rest) | x == y = go (y:rest) | otherwise = x : go (y:rest) -- 测试:uniqueColoursByLength cData 会返回 ["Red","Blue","Yellow"]
这里的comparing length是Data.Ord提供的工具函数,能把一个提取函数(比如length)转换成比较函数;<>则是把两个比较函数组合起来——先按长度比,长度相同再用默认的字符串比较。
关于sortBy的核心用法
sortBy的参数是一个比较函数,该函数接受两个元素,返回Ordering类型的值:
LT:表示第一个元素应该排在第二个元素前面EQ:表示两个元素排序优先级相同GT:表示第一个元素应该排在第二个元素后面
默认的sort其实就是sortBy compare,其中compare是Ord类型类提供的默认比较函数。
内容的提问来源于stack exchange,提问作者timedestoyer444
相关产品推荐
相关产品推荐

