【问题标题】:Counting unique elements in a list计算列表中的唯一元素
【发布时间】:2010-09-14 16:40:41
【问题描述】:

是否有标准高阶函数的直接组合来计算列表中的唯一元素?

例如结果

[1, 1, 4, 0, 4, 4]

应该是这样的

[(1,2), (4,3), (0,1)]

【问题讨论】:

  • 订单重要吗?如果是这样,顺序是什么?第一次出现的顺序?

标签: list haskell unique


【解决方案1】:

使用 Data.Map 和元组部分:

 count = Map.fromListWith (+) . map (, 1)

(如果您需要列表,请添加Map.toList。)

【讨论】:

    【解决方案2】:

    如果顺序不重要,这可行:

    map (\xs@(x:_) -> (x, length xs)) . group . sort
    

    group . sort 会给你一个列表列表,其中所有彼此相等的元素都被分组到同一个子列表中(没有排序,只有连续相等的元素会被组合在一起)。然后map 将每个子列表转换为(element, lengthOfSublist)-tuple。

    如果要按第一次出现对结果进行排序,可以在排序前使用 zip 为每个元素添加索引,然后在分组后再次按该索引排序,然后删除索引。

    【讨论】:

    • 在大型列表中排序可能非常昂贵。使用 KennyTM 或 sdcwc 的解决方案可能会更好,以获得更快的性能。
    • @GeneralBecos 为什么排序会比创建地图慢?两者都是O(n log n)
    • 因为假设你正在做一个频率分布,只有最坏情况下的元素数量将与列表中的元素数量相同。在更常见的情况下,分布中的元素数量会少得多。因此,平均而言,该地图将优于排序。
    • @GeneralBecos 是的,地图中的元素数量会更少,但我不明白这如何降低创建地图的成本。您仍然为列表中的每个元素调用 insert 一次,并且每次调用 insert 都需要 O(log n) 时间 - 无论该元素是否已经在地图中。
    • 在最坏的情况下需要O(log n)。平均而言,它需要 O(log m) 其中 m << n
    【解决方案3】:

    最简单的方法是对项目进行排序,使用“分组”将它们放入相同元素的子列表中,然后对每个子列表中的项目进行计数。

    map (\xs -> (head xs, length xs)) . group . sort
    

    【讨论】:

    • 顺便说一下,您可以使用 Control.Arrow 模块将\xs -> (head xs, length xs) 写成head &&& length
    【解决方案4】:

    如果列表只包含整数,你也可以使用

     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
    

    但效率较低。

    以上所有解决方案都忽略了原来的顺序。

    【讨论】:

    • 我敢打赌,这还不包括最近对容器库的速度改进。
    【解决方案5】:

    您所说的只是关于排序数据的run length encoding:免费在线书籍 Real World Haskell 有一个great example of this。您需要在通过 runLengthEncoder 之前对列表进行排序。

    【讨论】:

    • 不是 RLE。 RLE 会给[(1,2),(4,1),(0,1),(4,2)]
    • @KennyTM 请注意,我说的是“排序数据”。所以不完全是RLE,但我认为几乎是排序输入;不是吗?
    猜你喜欢
    • 2020-06-27
    • 2020-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-13
    • 1970-01-01
    • 1970-01-01
    • 2015-04-18
    相关资源
    最近更新 更多