假设有一些整数列表:
#--------------------------------------
0 [0,1,3]
1 [1,0,3,4,5,10,...]
2 [2,8]
3 [3,1,0,...]
...
n []
#--------------------------------------
问题是合并至少有一个公共元素的列表。因此,仅给定部分的结果如下:
#--------------------------------------
0 [0,1,3,4,5,10,...]
2 [2,8]
#--------------------------------------
在大数据(元素只是数字)上执行此操作的最有效方法是什么?tree
结构是否值得考虑?
我现在通过将列表转换成sets
并迭代交叉点来完成这项工作,但是速度很慢!此外,我有一种感觉,是如此基本!此外,实现缺少某些东西(未知),因为有些列表有时仍然未合并!话虽如此,如果你提议自我实现,请慷慨大方,并提供一个简单的示例代码[显然,Python是我的最爱:)]或pesudo代码。
更新1:
下面是我使用的代码:
#--------------------------------------
lsts = [[0,1,3],
[1,0,3,4,5,10,11],
[2,8],
[3,1,0,16]];
#--------------------------------------
功能是(小车!!):
#--------------------------------------
def merge(lsts):
sts = [set(l) for l in lsts]
i = 0
while i < len(sts):
j = i+1
while j < len(sts):
if len(sts[i].intersection(sts[j])) > 0:
sts[i] = sts[i].union(sts[j])
sts.pop(j)
else: j += 1 #---corrected
i += 1
lst = [list(s) for s in sts]
return lst
#--------------------------------------
结果是:
#--------------------------------------
>>> merge(lsts)
>>> [0, 1, 3, 4, 5, 10, 11, 16], [8, 2]]
#--------------------------------------
更新2: 根据我的经验,下面由Niklas Baumstark给出的代码对于简单的例子来说要快一点。还没有测试“Hooked”给出的方法,因为它是完全不同的方法(顺便说一下,它看起来很有趣)。 所有这些的测试程序可能很难或不可能保证结果。我将使用的实际数据集是如此庞大和复杂,因此不可能仅仅通过重复来跟踪任何错误。这是我需要100%满足的可靠性的方法之前,推动它在一个大的代码作为一个模块的位置。简单来说,Niklas的方法更快,简单集合的答案当然是正确的 但是,我如何确保它对真正的大型数据集有效?因为我无法直观地跟踪错误!
更新3: 注意,对于这个问题,方法的可靠性比速度重要得多。我希望最终能够将Python代码转换为Fortran以获得最大的性能。
更新4:
在这篇文章中有许多有趣的观点,并慷慨地给出了答案,建设性的评论。我建议大家通读一遍。请接受我对这个问题的发展、令人惊奇的答案以及建设性的评论和讨论的赞赏。
我试着总结在这个问题和duplicate one中关于这个主题所说和所做的一切。
我试着测试每个解决方案(所有代码here)。
测试
这是来自测试模块的
TestCase
:这个测试是假设一个集合列表作为结果,所以我不能测试两个与列表一起工作的suluons。
我无法测试以下各项:
在我能测试的那些中,有两个失败了:
时机
性能与所采用的数据测试密切相关。
到目前为止,有三个答案试图为他们和其他人的解决方案计时。因为他们使用了不同的测试数据,所以他们得到了不同的结果。
Niklas benchmark很荒谬。有了banchmark,人们可以做不同的测试来改变一些参数。
我使用了他在自己的答案中使用的三组参数,我将它们放在三个不同的文件中:
这是我得到的结果:
来自文件:
timing_1.txt
来自文件:
timing_2.txt
来自文件:
timing_3.txt
根据Sven的测试数据,我得到了以下结果:
最后通过Agf的基准测试,我得到了:
正如我在开头所说的,所有代码都可以在this git repository获得。所有合并函数都在一个名为
core.py
的文件中,其中每个以_merge
结尾的函数都将在测试期间自动加载,因此添加/测试/改进您自己的解决方案应该不难。如果有什么不对劲的地方,也请告诉我,这是一个很大的编码过程,我可以用一些新的眼光:)
我的尝试:
基准:
这些计时显然取决于基准测试的特定参数,如类数、列表数、列表大小等。请根据需要调整这些参数,以获得更有用的结果。
下面是我的机器上不同参数的一些输出示例。它们表明,所有算法都有其优缺点,这取决于它们获得的输入类型:
使用矩阵操作
请允许我在回答之前加上以下评论:
这样做是错误的。它很容易出现数值不稳定,而且速度比其他方法慢得多,风险自负。
尽管如此,我还是忍不住从动态的角度来解决这个问题(我希望你能对这个问题有一个新的视角)。在理论中,这应该一直有效,但特征值计算常常会失败。我们的想法是将列表看作一个从行到列的流。如果两行共享一个公共值,则它们之间存在连接流。如果我们把这些水流看作水,当它们之间有一条连接路径时,我们就会看到这些水流聚集成小水池。为了简单起见,我将使用较小的集合,尽管它也适用于您的数据集:
我们需要把数据转换成流程图。如果行i流入值j中,我们将其放入矩阵中。这里有3行和4个唯一值:
通常,您需要更改
4
来捕获您拥有的唯一值的数量。如果集合是从0开始的整数列表,您只需将其设为最大数即可。我们现在执行特征值分解。准确地说是SVD,因为我们的矩阵不是平方的。我们只想保留这个答案的3x3部分,因为它将代表池的流量。实际上,我们只需要这个矩阵的绝对值;我们只关心这个簇空间中是否有流。
我们可以把这个矩阵M看作一个马尔可夫矩阵,并通过行规范化使它显式。一旦我们得到这个,我们就计算(左)特征值分解。在这个矩阵中。
现在,一个不连通(非遍历)马尔可夫矩阵具有一个很好的性质,即对于每个不连通簇,都有一个统一的特征值。与这些单位值相关的特征向量是我们想要的:
由于前面提到的数值不稳定性,我不得不使用.999。现在,我们结束了!现在,每个独立的集群都可以拉出相应的行:
其目的是:
把
X
改成lst
就可以得到[ 0 1 3 4 5 10 11 16] [2 8]
。附录
为什么这可能有用?我不知道你的底层数据来自哪里,但是当连接不是绝对的时会发生什么?假设第
1
行有80%的时间有条目3
-您如何概括这个问题?上面的flow方法可以很好地工作,并且完全由.999
值参数化,离单位越远,关联就越松散。视觉表现
因为一张图片值1K个单词,这里是矩阵a和V的图,分别是我的例子和你的
lst
。注意在V
中如何分成两个簇(它是一个块对角矩阵,排列后有两个块),因为每个示例只有两个唯一的列表!更快的实现
事后看来,我意识到你可以跳过SVD步骤,只计算一次反编译:
这种方法的优点(除了速度)是
M
现在是对称的,因此计算速度更快、更精确(无需担心虚值)。相关问题 更多 >
编程相关推荐