2013-10-25 5 views
2

Скажите, есть ли список списков, например [[1,3,4],[1,5,6,7],[2,8,0]] или ["QQQ", "RRRR", "TTTTT"], есть ли функция, которая будет упорядочивать их по количеству элементов во внутренних списках, то есть в списке Int, список из 4 элементов идет спереди и в списке String s, T s идет вперед, а затем R s?Заказ списка списков в Haskell

+0

так, [SortBy] (http://www.haskell.org/ghc/ Docs/7,6-последняя/HTML/библиотеки/база-4.6.0.1/Data-list.html # v: SortBy)? –

ответ

3

Использование sortBy с пользовательским предикатом:

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]] 

Редактировать: Спасибо @JJJ за более красивый вариант

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]] 
+2

'\ e1 e2 -> compare (длина e2) (длина e1)' == 'flip $ сравнение длины'. – JJJ

+1

Вы можете сделать свой sortBy компаратор чистым путем импорта 'Data.ord.comparing'. Тогда вы можете написать 'sortBy (сравнивая длину) l' – Squidly

+0

Я действительно думал больше о сравнении, чем' compare'. :-) –

1

sortBy из Data.List и comparing от Data.Ord поможет вы.

foo = sortBy (comparing (negate . length)) 

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

Я хочу добавить еще одно решение, которое запоминает длины заданных списков. В противном случае длины пересчитываются с каждым сравнением, что будет означать много накладных расходов для больших списков.

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) 

Если вы хотите, чтобы списки одинаковой длины упорядочиваются лексикографически, вы можете использовать несколько проще

sortByLen' :: (Ord a) => [[a]] -> [[a]] 
sortByLen' = map snd . sort . map ((negate . length) &&& id) 
Смежные вопросы