1

I'm looking for a straight-forward combination of standard higher-order functions to compress a list by counting repetitive elements. For example the result for

"abbccccb"

would be :

 [(1, 'a'), (2, 'b'), (4, 'c'), (1, 'b')] 

another example, the result for

(sort "abrakadabra") 

would be:

[(5, 'a'), (2, 'b'), (1, 'd'), (1, 'k'), (2, 'r')]
4

3 回答 3

10

首先使用Data.List.group. 这为您提供了相同元素的运行列表,例如

> group "abbccccb"
["a","bb","cccc","b"]

然后,map在这个列表中,取每次运行的headlength。这可以通过以下&&&操作符优雅地完成Control.Arrow

> map (length &&& head) . group $ "abbccccb"
[(1,'a'),(2,'b'),(4,'c'),(1,'b')]
于 2013-04-27T17:29:25.297 回答
1

我写了一个只使用基本函数的代码。

f :: Eq a => [a] -> [(Int, a)]
f [] = []
f (x:xs) = (1 + length (takeWhile (==x) xs), x) : f (dropWhile (==x) xs)

我希望这个能帮上忙!。

于 2013-04-27T18:22:05.213 回答
0

您还可以使用Control.Applicative和应用函子实例(->) e

map ((,) <$> length <*> head) . group

如果你现在想要一个三倍的ord价值,那真的很容易!

map ((,,) <$> length <*> head <*> ord . head) . group

然而,匿名函数对读者来说可能更清楚。

map (\xs -> (length xs, head xs, (ord . head) xs) . group
于 2015-09-19T19:25:47.367 回答