简体   繁体   中英

Haskell. Sort by second element in the list of tuples

I have a code histogram , which shows the number of all characters in String.

histogram :: String -> [(Char, Int)]
histogram = foldr help [] where
    help x [] = [(x,1)] 
    help x ((y,z):yzs)
      | x == y = (y,z+1) : yzs 
      | otherwise = (y,z) : help x yzs

But the result is shown in a chaotic order. I want to sort the result by the second element of the list (ie by numbers). For this I implemented ssort code but it sorts only by the first element (char).

import Data.List (minimum, delete)

ssort :: Ord t => [t] -> [t]
ssort [] = []
ssort xs = x : ssort (remove x xs) where
     x = minimum xs

remove :: Eq a => a -> [a] -> [a]
remove _ [] = [] 
remove y (x:xs) | y == x = xs 
    | otherwise = x : remove y xs
 

Input: ssort [('a',1), ('g', 6), ('o',2), ('f',0)]

Output: [('a',1),('f',0),('g',6),('o',2)] (instead of [('f',0),('a',1),('o',2),('g',6)])

I also don't want to use any other builtins, as sort, sortOn and sortBy, I want to implement my own function.

How can I make it so that only the second elements are compared?

You may provide your own definition of minimumBy :

minimumBy2 :: Ord t2 => [(t1, t2)] -> (t1, t2)
minimumBy2 (h:t) = go h t where
  go x [] = x
  go x (h0:t0) = go (min x h0) t0
minimumBy2 [] = error "minimumBy2: Empty list"

You can then use it in place of minimum in ssort and it should work.

Assuming you don't want to use minimumBy:: Foldable t => (a -> a -> Ordering) -> ta -> a as well.

You can take advantage on how are tuples compared – first by the first element and then by the second. Therefore you can first swap all of the elements of your histogram, then sort and finally swap back:

ssortOn2 :: (Ord t1, Ord t2) => [(t1, t2)] -> [(t1, t2)]
ssortOn2 = map swap . ssort . map swap 

(leaving all other functions unchanged)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM