You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 12:10:27