假设我们有一张桌子:
id | aliases
-------------
0 | ['a0', 'a1', 'a4', 'a11']
1 | ['a3', 'a5']
2 | ['a16', 'a18']
3 | ['a6', 'a8', 'a10']
4 | ['a7', 'a8', 'a9']
5 | ['a3', 'a12', 'a14']
6 | ['a5', 'a16', 'a17']
,我想将所有映射到同一个id
的{{1}}分组在一起;换句话说,最终结果将所有aliases
相交的id
交叉在一起,以递归方式应用。在上述情况下,我们将:
aliases
映射到0
['a0', 'a1', 'a4', 'a11']
,1
,2
和5
映射到6
['a3', 'a5', 'a12', 'a14', 'a16', 'a17', 'a18']
和3
映射到4
是否有一种有效的方法来做到这一点?在我的实际用例中,我大约有1500万行。
有一种幼稚的方法,流传输行并检查到目前为止,每个新行中['a6', 'a7', 'a8', 'a9', 'a10']
的每个元素是否都在aliases
中处理过;如果是这样,则将所有具有匹配的aliases
的行收集在一起id
,并将它们映射到匹配的aliases
的并集。
但是,这种方法在计算上似乎不切实际。
答案 0 :(得分:0)
要在此表上运行O(n*len(groupcount)
复杂性代码并不难,只是让我无所适从:
假设您将id
作为ID的列表,将aliases
作为ID的列表,则可以执行以下操作:
bins = []
sets = []
for i in id: # Assume from (0 - n)
alias = aliases[i]
in_set = False
for j in range(len(sets)):
if len(sets[j].intersection(set(alias))) > 0:
sets[j].update(set(alias)) # add alias to set, if any difference
in_set = True
bins[j].append(i) # append id to bins
break
if not in_set:
bins.append([i])
sets.append(set(alias))
bins
将包含id
组,并且sets
中的相应元素将包含alias
组,您可以使用list()
将这些组转换回到list
。并且由于所有设置操作都是基于哈希的,因此可以确保您的程序在O(n*groupcount)
时间内运行。