性能:使用Vector(a,b)与Map a b在Haskell中进行计算

时间:2013-12-05 20:03:30

标签: haskell

我想玩文本统计,通过查看文本中的单词的相对频率(通常通过计算差异的绝对值之和)来成对地比较文本。这是文本数量的O(n ^ 2),因此每个文本中的预计算是可以的。我的问题是如何表示这样的统计数据。我尝试了两种方法:

  • Vector (T.Text,Double)手动排序(在预计算期间),并给出两个这样的向量,通过递归函数计算总和。 zip种类跟踪对的第一个元素的对齐方式,然后是fold

  • Map T.Text Double然后使用mergeWithKey (\k x y -> Just abs (x-y)) id id并使用foldl' (+) 0在顶部烹饪相同的内容。

第二种方式更具表现力,因为Map本质上是文本统计的真实含义,而且代码要短得多。但另一方面,Vector大约快3倍,代价是冗长,而且不知何故感觉错了,就像Map的天真实现一样。当然它错过了所有花哨的插入/更新/无论如何,但我不需要它。

我在这里遗漏了什么,比如第三个更适合任务的数据结构?

1 个答案:

答案 0 :(得分:2)

假设您有两个文档,都有O(m)个单词。然后,您的两个实现都需要O(m log m)时间来比较文档。

Sorting document 1 into a Vector (Text, Double) ~ O(m log m)
Sorting document 2 into a Vector (Text, Double) ~ O(m log m)
stepping through vector 1 and 2 ~ O(m)
total: O( m log m )

Storing document 1 in a Map Text Double ~ O(m log m)
Storing document 2 in a Map Text Double ~ O(m log m)
stepping through map 1 and map 2 ~ O(m log m)
total: O( m log m )

所以你的解决方案是渐近等价的,但这并不意味着它们都应该具有相同的运行时。针对实际数据进行测试以查看具有较小系数的数据是分析的工作,并且在这一点上完全合适。 Vector解决方案可能不那么优雅,但完全可信,它更有效。

在此之后,您可以通过接受近似值继续优化运行时间:

  • 选择一组你关心的大小为p的单词,p< m,只需检查该域的字数为O(p log p)的运行时间
  • 将单个单词散列为整数指示,并忽略O(m)运行时的冲突(假设恒定时间单词散列)