用于全外连接、内连接以及左连接和右连接的惰性迭代器
项目描述
full_outer_join
Python可迭代对象的全外连接、内连接以及左连接和右连接的惰性迭代器实现。
此实现使用排序合并连接,也称为合并连接,以O(n)时间复杂度(相对于最长迭代器的长度)连接可迭代对象。
请注意,算法要求输入按连接键排序。
示例
(空白以使内容更清晰)
>>> list(full_outer_join.full_outer_join(
[{"id": 1, "val": "foo"} ],
[{"id": 1, "val": "bar"}, {"id": 2, "val": "baz"}],
key=lambda x: x["id"]
))
[
(1, ([{'id': 1, 'val': 'foo'}], [{'id': 1, 'val': 'bar'}])),
(2, ([ ], [{'id': 2, 'val': 'baz'}]))
]
为了消费输出,您的业务逻辑可能看起来像
for group_key, key_batches in full_outer_join.full_outer_join(left, right):
left_rows, right_rows = key_batches
if left_rows and right_rows:
# This is the inner join case.
pass
elif left_rows and not right_rows:
# This is the left join case (no matching right rows)
pass
elif not left_rows and right_rows:
# This is the right join case (no matching left rows)
pass
elif not left_rows and not right_rows:
raise Exception("Unreachable")
函数
名称 | 描述 |
---|---|
full_outer_join(*iterables, key=lambda x: x) |
对任意数量的迭代器执行全外连接,返回所有迭代器中每个键的(key, (list[row], ...)) 。 |
inner_join(*iterables, key=lambda x: x) |
在所有迭代器之间执行内连接,返回仅存在于所有迭代器中的键的(key, (list[row], ...)) 。 |
left_join(left_iterable, right_iterable, key=lambda x: x) |
在两个迭代器上执行左连接,返回left_iterable 中每个唯一键的键。 |
right_join(left_iterable, right_iterable, key=lambda x: x) |
在两个迭代器上执行右连接,返回right_iterable 中每个唯一键的键。 |
cross_join(join_output, null=None) |
在full_outer_join 或inner_join 的输出上进行笛卡尔积(交叉)连接,为每一行生成(key, (iter1_row, ...)) 。这是为了完整性实现的,可能并不实用。对于缺少key 行迭代的可迭代对象,在输出中用null 替换。 |
为什么?
- 您的输入已经排序,您不希望消耗输入迭代器。
- 您的业务逻辑从消费连接输出中受益,可以显式处理每个输入可迭代对象的匹配和无匹配情况。
- 您疯了。您的思维被关系模型彻底破坏了。
更多示例
查看test_insanity.py,其中有一个将SQL查询手动编译成迭代器的愚蠢示例。
感谢
这最初是一个提交给more_itertools项目的PR,该项目对设计给出了很好的反馈,但最终不想合并。