ikemonn's blog

技術ネタをちょこちょこと

【Haskell】SortByを使う

Ninety-Nine Haskell Problems

Haskellの勉強をしていて、(Ninety-Nine Haskell Problems)https://wiki.haskell.org/99_questionsを解いている。

そこで、sortの問題が出てきたので解いた。

Problem 28 Sorting a list of lists according to length of sublists

a) We suppose that a list contains elements that are lists themselves. The objective is to sort the elements of this list according to their length. E.g. short lists first, longer lists later, or vice versa.

Example in Haskell:

Prelude>lsort ["abc","de","fgh","de","ijkl","mn","o"] Prelude>["o","de","de","mn","abc","fgh","ijkl"]

解答例 1

下記のいずれでも正解

import Data.List

lsort::[[a]]->[[a]]
lsort = sortBy (\xs ys -> compare (length xs) (length ys))

解説

sortBy :: (a -> a -> Ordering) -> [a] -> [a]

compare :: a -> a -> Ordering

sortByは、(a -> a -> Ordering)を第1引数にとるので、比較したいものとcompareを組み合わせればよい。

解答例 2

import Data.List
import Data.Function

lsort::[[a]]->[[a]]
lsort = sortBy (compare `on` length)

解説

on :: (b -> b -> c) -> (a -> b) -> a -> a -> c 

(*) `on` f = \x y -> f x * f y.

上記の記述をonを使って簡潔に表現できる。

解答例 3

import Data.List
import Data.Ord(comparing)

lsort::[[a]]->[[a]]
lsort = sortBy (comparing length)

解説

comparing :: Ord a => (b -> a) -> b -> b -> Ordering

comparing p x y = compare (p x) (p y)

解答例1をcomparingを使って書き換えると上記のように表現できる。