James
James

Reputation: 161

Ordering a list of lists in Haskell

Say if I had a list of lists like [[1,3,4],[1,5,6,7],[2,8,0]] or ["QQQ", "RRRR", "TTTTT"] , is there a function that will order them by the number of elements in inner lists i.e. so in the Int list, the 4 element list goes to the front and in the Strings list, the Ts go to the front and then the Rs?

Upvotes: 4

Views: 2027

Answers (3)

Petr
Petr

Reputation: 63359

I'd like to add another solution that memoizes the lengths of given lists. Otherwise the lengths are recomputed with each comparison, which will mean a lot of overhead for large lists.

import Control.Arrow ((&&&))
import Data.List (sort, sortBy)
import Data.Ord (comparing)

sortByLen :: [[a]] -> [[a]]
sortByLen = map snd . sortBy (comparing fst) . map ((negate . length) &&& id)

If you also want that lists of the same length get sorted lexicographically, you can use slightly simpler

sortByLen' :: (Ord a) => [[a]] -> [[a]]
sortByLen' = map snd . sort . map ((negate . length) &&& id)

Upvotes: 0

vek
vek

Reputation: 1543

sortBy from Data.List and comparing from Data.Ord will help you.

foo = sortBy (comparing (negate . length))

bar = foo ["QQQ", "RRRR", "TTTTT"]

Upvotes: 1

fjarri
fjarri

Reputation: 9726

Use sortBy with a custom predicate:

Prelude> import Data.List
Prelude Data.List> let l = [[1,3,4],[1,5,6,7],[2,8,0]]
Prelude Data.List> sortBy (\e1 e2 -> compare (length e2) (length e1))  l
[[1,5,6,7],[1,3,4],[2,8,0]]

Edit: Thanks @JJJ for a more beautiful variant

Prelude Data.List> import Data.Ord
Prelude Data.List Data.Ord> sortBy (flip $ comparing length) l
[[1,5,6,7],[1,3,4],[2,8,0]]

Upvotes: 6

Related Questions