使用排序Haskell对对列表进行排序

时间:2012-04-07 15:59:08

标签: haskell

我有一个函数(频率),它计算列表中每个不同值出现在该列表中的次数。例如,

frequency "ababca" 

应该返回:

[(3, 'a'), (2, 'b'), (1, 'c')].

这很好但现在我需要使用此函数使用列表列表中的第一个元素对列表进行排序。

results   :: [Party ] -> [(Int, Party)]
results  xs = ??? frequency (sort xs) ??? 

所需输出的示例:

[(1, "Green"), (2, "Red"), (3, "Blue")]

以上不起作用,我不知道我能做什么。

使用常规'排序'

先谢谢你。

2 个答案:

答案 0 :(得分:8)

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

results xs = sortBy (compare `on` fst) (frequency xs)

-- or, if you prefer
results xs = sort (frequency xs)

指向onsortBycomparefst的文档的链接。

区别在于sort按每对的第一个元素的升序排序,打破与对的第二个元素的打破中断,而sortBy (compare `on` fst)显式只查看第一个元素每一对。

答案 1 :(得分:2)

如果您只能使用sort而不是sortBy(出于某种原因!),那么您需要确保这些项的类型是Ord的实例。碰巧的是,所有元组(最大为15)都有Ord个实例,前提是 all 元组中的位置也有Ord个实例。

您提供的(1, "Green"), (2, "Red"), (3, "Blue")]示例应该排序正常(尽管相反),因为IntString都有Ord个实例。

但是,在代码段中,您还提到了Party类型而没有实际说明它是什么。如果它不仅仅是String之类的别名,您可能必须为它定义一个Ord实例,以满足元组的内置Ord实例。

您可以在声明类型时使用deriving为Haskell创建实例

 data Party = P1 | P2 | P3 | P4 -- e.g.
     deriving (Eq,Ord)

或自己声明:

 instance Ord Party where
     -- you don't care about the ordering of the party values
     compare a b = EQ   

但是,正如dave4420所说,只使用sortBy会好得多,所以除非你有特殊的理由不这样做,否则我会这样做(即它是一个有限制的课程作业)。