查找列表列表中两个列表之间的公共元素的最快方法

时间:2017-10-19 13:23:54

标签: python list graph

我正在尝试识别有向图中的气泡结构(方向从左到右)。我从可能的起始节点开始走图,例如绿色节点。然后我向所有路径添加一个节点,在路径再次发散时添加路径副本,如下所示:

第一次迭代: [[3],[7]]

第二次迭代:[[3,4],[3,5],[7,8],[7,9]]

每次迭代后,我想检查是否有任何路径相交并将它们保存为已确认的气泡。目前我正在使用嵌套的for循环来比较每个路径,但路径的数量会变得非常大,因此脚本可能变得非常慢。路径的顺序很重要。

Example bubble

有关如何提高路径列表中路径与另一路径的比较速度的建议吗?

if

其中GetNextSegment只返回连接到给定函数的节点的节点列表(在这种情况下,是路径的最后一个节点)。 outEdges是一个字典:node:[out,going,edges]。在ComparePaths()中,当2个路径的.intersection()长度大于0时,确认气泡。

气泡是一种图形结构,其中2条路径发散(例如,从绿色节点)并最终再次聚集在一起。在这个例子中,气泡将从2变为11,它们之间有所有节点。

我不是要求一个完整的冒泡算法,只是为了快速比较所有其他路径的所有路径的想法。

1 个答案:

答案 0 :(得分:1)

不要使用列表列表,而应考虑使用一组元组(如果订单很重要)或一组frozensets(如果顺序无关紧要)。使用newPaths初始化newPaths = set(),然后将每个路径添加为元组或冻结集(可以清除)而不是列表:

for node in nextNodes:                                      
    newPath = tuple(path) + (node,)
    # or: newPath = frozenset(path).union({node})
    newPaths.add(newPath)

这可以使检查成员资格和交叉点更快一些。

通过两次循环paths,您似乎多次检查相同的路径。例如,如果path1等于(3, 4)path2等于(3, 5),则无需检查(3, 4)(3, 5)还有(3, 5)(3, 4),因为您的支票看似对称。您可以使用ComparePaths帮助程序简化itertools

from itertools import combinations

def ComparePaths(paths, putativeBubbleStartSegment):
    # This gets all combinations of paths without repeating any pairing.
    for path1, path2 in combinations(paths, 2)
        # Don't need to check the length of the intersection because an
        # empty set is always equivalent to "False" in an if statement.
        if set(path1).intersection(path2):
            # Bubble confirmed

看起来您的示例代码遗漏了一些细节(因为有未使用的函数参数和变量),但我在这里看到的并不是似乎它应该适用于您的工作试图做。因此,即使可能有其他方法可以改进您的算法,也很难建议任何其他加速。