是否有标准高阶函数的直接组合来计算列表中的唯一元素?
例如
的结果[1, 1, 4, 0, 4, 4]
会像
[(1,2), (4,3), (0,1)]
答案 0 :(得分:15)
使用Data.Map和元组部分:
count = Map.fromListWith (+) . map (, 1)
(如果您需要列表,请添加Map.toList
。)
答案 1 :(得分:11)
如果订单不重要,则可行:
map (\xs@(x:_) -> (x, length xs)) . group . sort
group . sort
将为您提供一个列表列表,其中所有彼此相同的元素被分组到相同的子列表中(没有排序,只有连续的相等元素将被组合在一起)。 map
然后将每个子列表转换为(element, lengthOfSublist)
- 元组。
如果要在第一次出现时对结果进行排序,可以在排序之前使用zip
为每个元素添加索引,然后在分组后,再次按该索引排序,然后删除索引。 / p>
答案 2 :(得分:7)
最简单的方法是将项目按顺序排序,使用“group”将它们放入相等元素的子列表中,然后计算每个子列表中的项目。
map (\xs -> (head xs, length xs)) . group . sort
答案 3 :(得分:6)
如果列表仅包含整数,您也可以使用
import qualified Data.IntMap as I
countElems1 :: [Int] -> [(Int, Int)]
countElems1 = I.toList . foldr (\k -> I.insertWith (+) k 1) I.empty
(请记住使用优化进行编译,否则这将比group . sort
方法慢2倍。使用-O2
它会稍微快14%。)
您还可以使用其中一个multiset packages,这使得函数变得如此简单
import qualified Math.Combinatorics.Multiset as S
countElems4 = S.toCounts . S.fromList
但效率低下。
以上所有解决方案都忽略了原始订单。
答案 4 :(得分:1)
你所谈论的只是排序数据run length encoding:免费在线书籍Real World Haskell有一个great example of this。在将其放入runLengthEncoder之前,您需要对列表进行排序。