有效的不同大小的列表比较

时间:2014-10-24 14:50:23

标签: python algorithm memory-efficient

我希望比较大约1000个不同大小的列表。每个列表可能包含数千个项目。我想比较每对列表,因此可能进行大约500000次比较。每个比较包括计算较大列表中存在的较小列表的数量(如果相同大小,则选择列表)。最后,我想使用这些计数对列表进行聚类。我希望能够为两种类型的数据执行此操作:

  1. 任何文字数据
  2. 相同长度的二进制数字字符串。
  3. 在python中有一种有效的方法吗?我查看了LShash和其他与聚类相关的算法,但它们似乎需要相同的长度列表。 TIA。

    试图阐明我的目标:

    列表A:汽车,挖掘,狗,。

    名单B:鱼,狗,狗。

    (在任何列表中都没有重复。虽然我认为它们可以相当容易,但没有排序。列表大小各不相同。)

    结果:2,因为' dog'和''在两个列表中。

    实际上,每个列表的长度可以是数千个,并且大约有1000个这样的列表,每个列表都必须相互比较。

    继续举例:

    列表C:狗,the,a,fish,fry。

    结果: AB:2 AC:2 BC:3

1 个答案:

答案 0 :(得分:0)

没有什么是超高速的,并且有很多数据(开始时有50万个结果),但以下内容应该适合现代硬件上的时间和空间预算。

如果可能,首先按长度排序列表,从最长到最短。 (我并不是指对每个列表进行排序;列表中元素的顺序是无关紧要的。我的意思是,对列表集合进行排序,以便您可以先处理最长的列表。)这样做的唯一要点是允许相似性要存储在半对角矩阵而不是全矩阵中的度量,这样可以节省一半的矩阵空间。因此,如果您在开始之前不知道列表的长度,那么这不是危机;它只是意味着你需要更多的空间。

注1:重要的是,只要没有列表重复元素,您建议的指标就是完全对称的。没有重复的元素,指标只是|A⋂B|,无论AB是否更长,因此当您计算AB的交集大小时,您可以填写(A,B)的相似度矩阵和(B,A)。)

注2:当我重读它时,算法的描述似乎让我感到困惑所以当它引用一个时,我将“list”改为“ list ”千位输入列表,留下“list”表示普通的Python列表。由于列表不能是Python词典中的键,因此假设列表是作为列表实现的,因此有必要以某种方式使用可以使用的标识符来标识每个列表作为关键。我希望这很清楚。

算法:

我们需要两个辅助结构:一个是(半对角线)结果矩阵,由成对的 list 标识符键入,我们将其初始化为全0。另一个是由唯一数据元素键入的字典,映射到 list 标识符列表。

然后,依次获取每个列表,对于该列表中的每个元素,我们执行以下操作:

  1. 如果该元素尚未出现在字典中,请添加该元素,映射到包含当前列表的标识符的单个元素列表。

  2. 如果元素出现在字典中,但相应的id列表中的最后一个元素是当前的id,那么我们找到了一个重复的元素。由于我们不期望重复元素,因此忽略它或发出错误消息。

  3. 否则,我们之前已经看过该元素,并且我们有一个列表的标识符列表,其中显示了该元素。对于每个这样的标识符,增加当前标识符与列表中的标识符之间的相似性计数。 (请注意,如果我们按长度以相反的顺序扫描列表,则列表中的所有标识符都对应于列表,它们至少与当前列表< / em>,这就是我们首先对列表进行排序的原因。)最后,将当前标识符附加到列表的末尾,以便下次找到该数据元素时, list 将会出现。

  4. 就是这样。空间要求为O(N2 + M),其中N列表的数量,M是所有列表的总大小。在最坏的情况下,时间要求基本上是O(M2) - 在每个列表只有一个元素并且它们都是相同元素的情况下。 (更准确地说,它是每个独特元素频率的平方和。)