2012-04-07 70 views
2

排序對列表我有一個函數(頻率),它計數列表中每個不同值的次數。例如,使用排序Haskell

frequency "ababca" 

應該返回:

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

也能正常工作,但現在我需要使用使用此功能列表的列表中的第一個元素對列表進行排序。期望輸出的

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

例如:

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

以上不工作,我不知道我能做些什麼。

使用常規「排序」

先謝謝您。

+1

請注意,您在Haskell使用逗號時使用分號。 – dave4420 2012-04-07 16:04:23

回答

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按照每一對的第一個元素的升序排序,與這些對的第二個元素打破tie-break,而sortBy (compare `on` fst)明確地只查看每一對的第一個元素。

+0

如何使用常規「排序」與上述內容相同? – ErHunt 2012-04-07 16:13:01

+1

@Badr看我的編輯。 – dave4420 2012-04-07 16:19:32

+1

您可以使用'(比較fst)'而不是'(比較'\ fst)''。 – pat 2012-05-03 23:10:21

2

如果您只能使用sort而不是sortBy(出於某種原因!),那麼您需要確保這些項目的類型是Ord的一個實例。碰巧,所有元組(最大大小爲15)都有Ord實例,前提條件是元組中的位置也有Ord實例。

您給出的(1, "Green"), (2, "Red"), (3, "Blue")]的示例應該排序良好(儘管相反),因爲IntString都有Ord實例。

但是,在代碼片段中,還提到了Party類型,但實際上沒有說明它是什麼。如果它不只是String之類的別名,則可能必須爲它定義一個Ord實例,以滿足元組的內置Ord實例。

您可以哈斯克爾爲您創建實例,使用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,所以我會這樣做,除非你有一個特定的原因不要(即它是一個有限制的班級作業)。