2

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

frequency "ababca" 

应该返回:

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

这工作正常,但现在我需要使用此函数使用列表列表中的第一个元素对列表进行排序。

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

所需输出的示例:

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

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

使用常规的“排序”

先感谢您。

4

2 回答 2

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)

on, sortBy, compare,的文档链接fst

不同之处在于,它sort按每对的第一个元素的升序排序,用对的第二个元素打破平局,而sortBy (compare `on` fst)明确地只查看每对的第一个元素。

于 2012-04-07T16:07:03.173 回答
2

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

您给出的示例(1, "Green"), (2, "Red"), (3, "Blue")]应该可以很好地排序(尽管相反),因为两者Int 都有String实例Ord

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

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

 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,所以我会这样做,除非你有特定的理由不这样做(即这是一个有限制的课堂作业)。

于 2012-04-07T16:52:57.797 回答