2017-05-09 71 views
1

我有两个数组是这样的:Python中的SQL风格内部连接?

[('a', 'beta'), ('b', 'alpha'), ('c', 'beta'), .. ] 

[('b', 37), ('c', 22), ('j', 93), .. ] 

我想产生类似:

[('b', 'alpha', 37), ('c', 'beta', 22), .. ] 

是否有一个简单的方法来做到这一点?

+1

你有试过什么吗? – depperm

+0

@depperm我认为一个for循环来检查是否匹配并推送到一个新的数组,但我认为可能有一些内置函数可以使它更容易。 –

+2

检查这个线程:http://stackoverflow.com/questions/7776907/sql-join-or-rs-merge-function-in-numpy – Cleared

回答

1

我建议哈希鉴别加入像方法:

l = [('a', 'beta'), ('b', 'alpha'), ('c', 'beta')] 
r = [('b', 37), ('c', 22), ('j', 93)] 
d = {} 
for t in l: 
    d.setdefault(t[0], ([],[]))[0].append(t[1:]) 
for t in r: 
    d.setdefault(t[0], ([],[]))[1].append(t[1:]) 
from itertools import product 
ans = [ (k,) + l + r for k,v in d.items() for l,r in product(*v)] 

结果在:

[('c', 'beta', 22), ('b', 'alpha', 37)] 

由于它避免了计算product(l,r),然后按照朴素方法进行过滤,因此它具有比O(nm)更接近O(n + m)的更低复杂度。

主要来自:弗里茨Henglein的有歧视性的关系代数加入和懒惰产品

它也可以写为:

def accumulate(it): 
    d = {} 
    for e in it: 
     d.setdefault(e[0], []).append(e[1:]) 
    return d 
l = accumulate([('a', 'beta'), ('b', 'alpha'), ('c', 'beta')]) 
r = accumulate([('b', 37), ('c', 22), ('j', 93)]) 
from itertools import product 
ans = [ (k,) + l + r for k in l&r for l,r in product(l[k], r[k])] 

这种积累都分别列出(转[(a,b,...)]{a:[(b,...)]}),然后计算它们的键集之间的交集。这看起来更干净。如果字典之间不支持l&r,则将其替换为set(l)&set(r)

1

没有内置方法。我想,像numpy这样的软件包将会提供额外的功能。

但是,如果你想解决它,而无需使用任何额外的软件包,你可以使用一个衬垫这样的:

ar1 = [('a', 'beta'), ('b', 'alpha'), ('c', 'beta')] 
ar2 = [('b', 37), ('c', 22), ('j', 93)] 
final_ar = [tuple(list(i)+[j[1]]) for i in ar1 for j in ar2 if i[0]==j[0]] 
print(final_ar) 

输出:

[('b', 'alpha', 37), ('c', 'beta', 22)]