Python中的SQL风格内连接?

Posted

技术标签:

【中文标题】Python中的SQL风格内连接?【英文标题】:SQL style inner join in Python? 【发布时间】:2017-05-09 12:54:06 【问题描述】:

我有两个这样的数组:

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

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

我想制作类似的东西:

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

有没有简单的方法可以做到这一点?

【问题讨论】:

你尝试过什么吗? @depperm 我考虑了一个 for 循环来检查是否匹配并推送到一个新数组,但我认为可能有一些内置函数可以使它更容易。 查看这个帖子:***.com/questions/7776907/… ***.com/questions/17682721/… 【参考方案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)]

这具有比 O(nm) 更接近 O(n+m) 的复杂度,因为它避免了计算 product(l,r) 然后像天真的方法那样进行过滤。

主要来自:Fritz 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)

【讨论】:

【参考方案2】:

没有内置方法。我认为添加像 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)]

【讨论】:

以上是关于Python中的SQL风格内连接?的主要内容,如果未能解决你的问题,请参考以下文章

SQL中的左连接与右连接,内连接有啥区别

SQL内连接与外连接的区别

sql中的内连接和外连接

SQL中内连接使用详细说明

Linq 和 SQL的左连接右连接内链接

08_MySQL DQL(SQL99标准)_多表连接查询中的内连接