python的关系工具。
reltools的Python项目详细描述
python的关系工具。 这将两个数据(按某些键排序)关联起来,比如sql连接。
灵感来自itertools.groupby, 只要对输入数据进行排序,几乎所有进程都会被惰性地评估, 从而减少了内存使用。 此功能用于不使用任何SQL引擎的大数据连接。
功能
一对多
一对多关系由relate_one_to_many提供。
在这里,输入左侧(lhs)和右侧(rhs) 按第一(和第二)键排序。
>>> lhs = [ ... (1, 'a', 's'), ... (2, 'a', 't'), ... (3, 'b', 'u'), ... ] >>> rhs = [ ... (1, 'a', 'v'), ... (1, 'b', 'w'), ... (3, 'b', 'x'), ... ]
relate_one_to_many相关rhs项 使用第一个项作为键的每个lhs项。
>>> from reltools import relate_one_to_many >>> one_to_many_related = relate_one_to_many(lhs, rhs) >>> for left, right in one_to_many_related: ... left, list(right) ((1, 'a', 's'), [(1, 'a', 'v'), (1, 'b', 'w')]) ((2, 'a', 't'), []) ((3, 'b', 'u'), [(3, 'b', 'x')])
您可以使用自定义键函数 不仅适用于relate_one_to_many,还适用于api函数。
>>> import operator >>> custom_key = operator.itemgetter(0, 1) >>> one_to_many_related = relate_one_to_many( ... lhs, rhs, lhs_key=custom_key, rhs_key=custom_key) >>> for left, right in one_to_many_related: ... left, list(right) ((1, 'a', 's'), [(1, 'a', 'v')]) ((2, 'a', 't'), []) ((3, 'b', 'u'), [(3, 'b', 'x')])
OneToManyChainer有助于将许多rhsiterables与lhs关联起来。
>>> another_rhs = [ ... ('s', 'f'), ... ('t', 'g'), ... ('t', 'h'), ... ] >>> from reltools import OneToManyChainer >>> chainer = OneToManyChainer(lhs) >>> chainer.append(rhs) >>> chainer.append( ... another_rhs, ... lhs_key=operator.itemgetter(2), ... rhs_key=operator.itemgetter(0), ... ) >>> for left, right, another_right in chainer.chain(): ... left, list(right), list(another_right) ((1, 'a', 's'), [(1, 'a', 'v'), (1, 'b', 'w')], [('s', 'f')]) ((2, 'a', 't'), [], [('t', 'g'), ('t', 'h')]) ((3, 'b', 'u'), [(3, 'b', 'x')], [])
左外连接
左外部连接由left_join提供。 当sql left outer joining返回所有组合时, 这将返回这对项。 注意,right可以为空,就像sql左连接一样。
>>> from reltools import left_join >>> lhs = [(1, 'a'), (1, 'b'), (2, 'c'), (4, 'd')] >>> rhs = [(1, 's'), (1, 't'), (3, 'u'), (4, 'v')] >>> relations = left_join(lhs, rhs) >>> for left, right in relations: ... list(left), list(right) ([(1, 'a'), (1, 'b')], [(1, 's'), (1, 't')]) ([(2, 'c')], []) ([(4, 'd')], [(4, 'v')])
右外部连接
不支持右外部连接 因为它是左和右的对立面。 使用left_join(rhs, lhs, rhs_key, lhs_key)。
完全外部连接
完全外部连接,这是reltools的原始功能, 由outer_join提供。 与left_join相反,完全外部连接保留键 只在rhs中。
>>> from reltools import outer_join >>> lhs = [(1, 'a'), (1, 'b'), (2, 'c'), (4, 'd')] >>> rhs = [(1, 's'), (1, 't'), (3, 'u'), (4, 'v')] >>> relations = outer_join(lhs, rhs) >>> for left, right in relations: ... list(left), list(right) ([(1, 'a'), (1, 'b')], [(1, 's'), (1, 't')]) ([(2, 'c')], []) ([], [(3, 'u')]) ([(4, 'd')], [(4, 'v')])
内部连接
内部连接由inner_join提供。 与left_join相反,right不能为空, 比如sql内部连接。
>>> from reltools import inner_join >>> relations = inner_join(lhs, rhs) >>> for left, right in relations: ... list(left), list(right) ([(1, 'a'), (1, 'b')], [(1, 's'), (1, 't')]) ([(4, 'd')], [(4, 'v')])
多对多
不支持类似sql的many-to-many使用内部表进行关联。 这是因为reltools只支持排序的数据 也不喜欢随机访问。 为了实现many-to-many关联,对预处理和 使用外部连接或内部连接。
记忆效率
几乎所有的过程都被惰性地评估, 从而减少了内存使用。 (您可以通过以下命令来尝试效率 RELTOOLS_TRY_COUNT=10000000 python -m doctest README.rst)
>>> import os >>> n = int(os.environ.get('RELTOOLS_TRY_COUNT', 1000)) >>> lhs = ((i, 'left') for i in range(n)) >>> rhs = ((i, 'right') for i in range(n)) >>> for left, right in relate_one_to_many(lhs, rhs): ... assert len(list(right)) == 1
开发
这个项目的结构基于Poetry。 所有测试都是用doctest编写的 和pytest一起跑。
poetry install poetry run pytest
为了保持稳定性,测试时还将执行以下检查。