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

Haskell中如何对元组列表使用groupBy按元组第二个元素分组

按元组第二个元素分组的Haskell实现

针对你的需求,根据输入列表的有序性不同,有两种高效的标准实现,都依赖Haskell base库自带的函数,不需要额外安装第三方包。

输入已按第二个元素排序(你的示例属于这种情况)

如果同分组键的元素已经在列表里连续排列,直接用Data.List.groupBy做线性扫描即可,时间复杂度O(n),是最优效率:

import Data.List (groupBy)
import Data.Function (on)

groupSnd :: Eq b => [(a, b)] -> [[(a, b)]]
groupSnd = groupBy ((==) `on` snd)

调用groupSnd [(3,2),(17,2),(50,3),(64,3)]就能直接得到你期望的输出结果。
这里on函数的作用是把相等判断的逻辑作用到两个元组的第二个元素上:即两个元组只要snd返回值相等,就判定为同组。

输入未按第二个元素排序

如果输入中同键元素是分散的(比如[(3,2), (50,3), (17,2)]),直接用groupBy会得到错误结果,此时先按分组键做排序再分组即可,时间复杂度O(n log n),是通用场景下的高效实现:

import Data.List (groupBy, sortOn)
import Data.Function (on)

groupSndUnsorted :: Ord b => [(a, b)] -> [[(a, b)]]
groupSndUnsorted = groupBy ((==) `on` snd) . sortOn snd

sortOn snd会先把所有元组按第二个元素升序排列,保证同键元素连续,后续分组逻辑和上面完全一致。

补充:无顺序要求的分组场景

如果你不需要保留分组的原有顺序,也可以用Data.Map.Strict做聚合插入,时间复杂度同样是O(n log n),适合分组键没有天然排序关系的场景:

import qualified Data.Map.Strict as M

groupSndMap :: Ord b => [(a, b)] -> [[(a, b)]]
groupSndMap = M.elems . foldr (\pair m -> M.insertWith (++) (snd pair) [pair] m) M.empty

内容的提问来源于stack exchange,提问作者Elfi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 06:48:31