这是参考之前的问题。
因为目前返回的内容是按字母顺序排列的,而我希望它按大小顺序排列,从百分比最高的字母开始向下?
你想要一个像
letterFrqs :: String -> [(Char, Float)]
和
letterFrqs "PLATYPUS" == [('A',36),('P',18),('L',9),('S',9),('T',9),('U',9),('Y',9)]
给定一个
frqLetters :: String -> [(Char, Float)]
和
frqLetters "PLATYPUS" == [('A',36),('L',9),('P',18),('S',9),('T',9),('U',9),('Y',9)]
所以你需要的是
letterFrqs = sortEm . frqLetters
和
sortEm :: [(Char, Float)] -> [(Char, Float)]
我们怎么写sortEm?好吧,我们可以sort按Float原样使用 s sort :: [Float] -> [Float],. 我们想将这种排序提升到我们的元组中。
通常,Haskell 函数有时可能具有类似名称的表兄弟。在这种情况下,sort :: Ord a => [a] -> [a]有一个表亲名为sortBy :: (a -> a -> Ordering) -> [a] -> [a]。这里的区别在于Ord实例是“内联的”。更具体地说,这里是Ord
instance Eq a => Ord a where
compare :: a -> a -> Ordering
所以我们注意到sortBy只是用定义实例的确切函数替换了sort's约束。确实,这就是实现的方式OrdOrdcomparesort
sort = sortBy compare
我们可以sortEm通过编写与元组上的实例等效的代码来编写,该Ord实例仅比较第二个元素(我们Float的 s!)。
那么我们该怎么做呢?好吧,我们可以将Ord实例用于Float.
compareOurTuples (char1, percent1) (char2, percent2) = compare percent1 percent2
sortEm = sortBy compareOurTuples
现在,对 Haskell 有敏锐眼光的人可能会注意到我们也可以compareOurTuples这样写
compareOurTuples tup1 tup2 = compare (snd tup1) (snd tup2)
这是一个常见的习惯用法,有点像预先组合一个函数“两次”。它被调用on并且它在Data.Function.
compareOurTuples = compare `on` snd
但是,这也是一个很常见的成语,结合compareand on,所以即使它也有一个特殊的名字。在Data.Ord我们有
comparing f = compare `on` f
所以我们在写作的时候实际上可以很省钱sortEm。
sortEm = comparing snd
这可能是某人实际编写此代码的方式。
letterFrqs = sortBy (comparing snd) . frqLetters
现在读起来有点像英语。