【问题标题】:Fastest algorithm for finding overlap between two very large lists?查找两个非常大的列表之间重叠的最快算法?
【发布时间】:2012-05-12 13:10:51
【问题描述】:

我正在尝试在 Python 中构建一个算法来过滤大量 RDF 数据。

我有一个包含大约 7 万个项目的列表,格式类似于 <"datum">

然后我有大约 6GB 的项目(三元组),格式为 <"A"> <"B"> <"C">

我想提取包含第一个列表中任何项目的所有三元组,然后从第一次提取中提取包含任何单个项目的任何三元组(最终效果是形成一个通过一步连接的图的分区到第一个列表中的种子)。

我还没有为此想出一个很好的算法(因为我没有接受过正规的 CS 培训,这对我没有帮助。)

到目前为止,我想出的最好的方法是首先将大列表中的三元组拆分为三个项目列表[<"A">, <"B">, <"C">] 的列表。然后我将其拆分为多个块,并使用多处理来创建进程,这些进程包含完整的小列表和大列表的一部分......

for line in big list:
    for item in small list:
      if item in line:
       bucket.append(line)

这个算法需要相当长的时间。

有没有更快的方法来做到这一点?如果有具体的算法,你可以给我名字,我会想办法实现它。

谢谢!

每个 cmets 的说明:

  1. 所有数据项都是字符串。所以小列表可能包含["Mickey", "Mouse", "Minny", "Cat"],大列表可能是[["Mickey","Pluto","Bluto"],["John", "Jane", "Jim]...]

  2. 每个大列表三元组中只有一个项目需要匹配小列表中的一个项目才能计数

  3. 小列表中的所有项目实际上都是唯一的,所以我没想过将它们转换为集合。不过我会试试的。

  4. 我可以创建任何我想要的中间结构。我现在正在尝试使用搁架构建的倒排索引。

【问题讨论】:

  • 是否允许在磁盘上构建中间结构?似乎您可以从“倒排索引”中受益,例如 {'A': [('A', B', 'C), ('A', 'X', 'Y')], ... }
  • 明确一点,在每个阶段匹配条目的确切标准是什么?所有<A><B><C> 都必须匹配吗?或者只是<A><B><C> 之一?过滤的第二阶段也有点模糊。一些示例数据可能会有所帮助?
  • 您应该提供一个简短示例,说明第一个列表包含的内容以及您希望结果列表包含的内容。
  • 数据是什么?数字?字符串?

标签: python algorithm list rdf


【解决方案1】:

您可能应该首先将小列表存储在一个集合中,这样查找速度会更快。这可以防止 big_list 中的每个项目都经历 70,000 次迭代。

small_list_set = set(small_list)
for line in big_list:
    for item in line:
        if item in small_list_set:
            bucket.append(line)

【讨论】:

  • 非常好的建议。这可能会快得多,因为在良好实现的set(使用散列键)中查找是O(1)时间,而不是在O(n)时间通过列表进行搜索。
  • 请注意,如果有多个匹配项,这(如 OP 的代码)将多次附加 line,这可能是不希望的(我不清楚究竟需要什么过滤)。这可以通过在bucket.append(line) 之后添加break 来轻松避免。
  • 我同意 - 我也不清楚 OP 到底想要什么。主要建议是使用一个集合将运行时间减少 70,000 倍左右。
  • 即使小列表中的项目已经是唯一的,使用 set() 确实要快得多。我想我最终会建立一个倒排索引,因为它可以很容易地执行第二步,即从与第一遍匹配的任何三元组中查找包含项目的三元组。建立索引需要很长时间,但一旦建立,查找速度非常快。
  • @rogueleaderr:这里我们使用set 不是因为其中的元素保证是唯一的,这是set 的一个属性,而是因为其中的查找要快得多。 (这是可能的,因为每个元素只能出现一次。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-30
  • 1970-01-01
  • 2020-10-24
  • 1970-01-01
相关资源
最近更新 更多