{ "info": { "author": "ymoch", "author_email": "ymoch.dev@gmail.com", "bugtrack_url": null, "classifiers": [ "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7" ], "description": "reltools\n========\n\n.. image:: https://travis-ci.org/ymoch/reltools.svg?branch=master\n :target: https://travis-ci.org/ymoch/reltools\n.. image:: https://codecov.io/gh/ymoch/reltools/branch/master/graph/badge.svg\n :target: https://codecov.io/gh/ymoch/reltools\n.. image:: https://badge.fury.io/py/reltools.svg\n :target: https://badge.fury.io/py/reltools\n.. image:: https://img.shields.io/badge/python-3.5+-blue.svg\n :target: https://www.python.org/\n.. image:: https://img.shields.io/lgtm/grade/python/g/ymoch/reltools.svg\n :target: https://lgtm.com/projects/g/ymoch/reltools/context:python\n\nRelation tools for Python.\nThis relates two data (sorted by certain keys) like SQL joining.\n\nInspired by `itertools.groupby `_,\nas long as input data are sorted, almost all processes are evaluated lazily,\nwhich results in the reduction of memory usage.\nThis feature is for the big data joining without any SQL engines.\n\nInstallation\n------------\n\nInstall with `pip `_.\n\n.. code-block:: sh\n\n pip install reltools\n\nFeatures\n--------\n\nOne-To-Many\n***********\n\n*One-to-many* relationing is provided by ``relate_one_to_many``.\n\nHere, input left-hand-side (``lhs``) and right-hand-side (``rhs``)\nare sorted in 1st (and also 2nd) keys.\n\n>>> lhs = [\n... (1, 'a', 's'),\n... (2, 'a', 't'),\n... (3, 'b', 'u'),\n... ]\n>>> rhs = [\n... (1, 'a', 'v'),\n... (1, 'b', 'w'),\n... (3, 'b', 'x'),\n... ]\n\n``relate_one_to_many`` relates ``rhs`` items\nto each ``lhs`` item using the first items as keys.\n\n>>> from reltools import relate_one_to_many\n>>> one_to_many_related = relate_one_to_many(lhs, rhs)\n>>> for left, right in one_to_many_related:\n... left, list(right)\n((1, 'a', 's'), [(1, 'a', 'v'), (1, 'b', 'w')])\n((2, 'a', 't'), [])\n((3, 'b', 'u'), [(3, 'b', 'x')])\n\nYou can use custom key functions\nfor not only ``relate_one_to_many`` but also API functions.\n\n>>> import operator\n>>> custom_key = operator.itemgetter(0, 1)\n>>> one_to_many_related = relate_one_to_many(\n... lhs, rhs, lhs_key=custom_key, rhs_key=custom_key)\n>>> for left, right in one_to_many_related:\n... left, list(right)\n((1, 'a', 's'), [(1, 'a', 'v')])\n((2, 'a', 't'), [])\n((3, 'b', 'u'), [(3, 'b', 'x')])\n\n``OneToManyChainer`` helps to relate many ``rhs`` iterables to ``lhs``.\n\n>>> another_rhs = [\n... ('s', 'f'),\n... ('t', 'g'),\n... ('t', 'h'),\n... ]\n>>> from reltools import OneToManyChainer\n>>> chainer = OneToManyChainer(lhs)\n>>> chainer.append(rhs)\n>>> chainer.append(\n... another_rhs,\n... lhs_key=operator.itemgetter(2),\n... rhs_key=operator.itemgetter(0),\n... )\n>>> for left, right, another_right in chainer.chain():\n... left, list(right), list(another_right)\n((1, 'a', 's'), [(1, 'a', 'v'), (1, 'b', 'w')], [('s', 'f')])\n((2, 'a', 't'), [], [('t', 'g'), ('t', 'h')])\n((3, 'b', 'u'), [(3, 'b', 'x')], [])\n\nLeft Outer Join\n***************\n\nLeft outer joining is provided by ``left_join``.\nWhile SQL left outer joining returns all the combinations,\nthis returns the pair of items.\nNote that the ``right`` can empty, like SQL left joining.\n\n>>> from reltools import left_join\n>>> lhs = [(1, 'a'), (1, 'b'), (2, 'c'), (4, 'd')]\n>>> rhs = [(1, 's'), (1, 't'), (3, 'u'), (4, 'v')]\n>>> relations = left_join(lhs, rhs)\n>>> for left, right in relations:\n... list(left), list(right)\n([(1, 'a'), (1, 'b')], [(1, 's'), (1, 't')])\n([(2, 'c')], [])\n([(4, 'd')], [(4, 'v')])\n\nRight Outer Join\n****************\n\nRight outer joining is not supported\nbecause it is left-and-right-opposite of left joining.\nUse ``left_join(rhs, lhs, rhs_key, lhs_key)``.\n\nFull Outer Join\n***************\n\nFull outer joining, which is an original feature of *reltools*,\nis provided by ``outer_join``.\nIn contrast to ``left_join``, full outer joining preserve keys\nthat are only in ``rhs``.\n\n>>> from reltools import outer_join\n>>> lhs = [(1, 'a'), (1, 'b'), (2, 'c'), (4, 'd')]\n>>> rhs = [(1, 's'), (1, 't'), (3, 'u'), (4, 'v')]\n>>> relations = outer_join(lhs, rhs)\n>>> for left, right in relations:\n... list(left), list(right)\n([(1, 'a'), (1, 'b')], [(1, 's'), (1, 't')])\n([(2, 'c')], [])\n([], [(3, 'u')])\n([(4, 'd')], [(4, 'v')])\n\nInner Join\n**********\n\nInner joining is provided by ``inner_join``.\nIn contrast to ``left_join``, ``right`` cannot be empty,\nlike SQL inner joining.\n\n>>> from reltools import inner_join\n>>> relations = inner_join(lhs, rhs)\n>>> for left, right in relations:\n... list(left), list(right)\n([(1, 'a'), (1, 'b')], [(1, 's'), (1, 't')])\n([(4, 'd')], [(4, 'v')])\n\nMany-To-Many\n************\n\nSQL-like *many-to-many* relationing using an internal table is not supported.\nThis is because *reltools* supports only sorted data\nand does not prefer random accessing.\nTo achieve *many-to-many* relationing, unnormalize data on preproceing and\nuse outer joining or inner joining.\n\nMemory Efficiency\n*****************\n\nAlmost all processes are evaluated lazily,\nwhich results in the reduction of memory usage.\n(You can try the efficiency by commands like\n``RELTOOLS_TRY_COUNT=10000000 python -m doctest README.rst``)\n\n>>> import os\n>>> n = int(os.environ.get('RELTOOLS_TRY_COUNT', 1000))\n>>> lhs = ((i, 'left') for i in range(n))\n>>> rhs = ((i, 'right') for i in range(n))\n>>> for left, right in relate_one_to_many(lhs, rhs):\n... assert len(list(right)) == 1\n\nDevelopment\n-----------\n\nThis project's structure is based on `Poetry `_.\nAll tests are written with `doctest `_\nand run with `pytest `_.\n\n.. code-block:: sh\n\n poetry install\n poetry run pytest\n\nFor stability, following checks are also run when testing.\n\n- `pep8 `_\n- `pyflakes `_\n- `pycodestyle `_\n\nLicense\n-------\n\n.. image:: https://img.shields.io/badge/License-MIT-brightgreen.svg\n :target: https://opensource.org/licenses/MIT\n\nCopyright (c) 2018 Yu MOCHIZUKI\n", "description_content_type": "text/x-rst", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/ymoch/reltools", "keywords": "", "license": "MIT", "maintainer": "ymoch", "maintainer_email": "ymoch.dev@gmail.com", "name": "reltools", "package_url": "https://pypi.org/project/reltools/", "platform": "", "project_url": "https://pypi.org/project/reltools/", "project_urls": { "Homepage": "https://github.com/ymoch/reltools", "Repository": "https://github.com/ymoch/reltools" }, "release_url": "https://pypi.org/project/reltools/0.9.4/", "requires_dist": [ "more-itertools (>=7.2,<8.0)" ], "requires_python": ">=3.5,<4.0", "summary": "Relation tools for Python.", "version": "0.9.4" }, "last_serial": 5759196, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "e77c3005eb761e0c47b14c1783c789eb", "sha256": "533e94064289bf27075bc01a6f0d00cbe572a37a56262433efa553ca944baa0a" }, "downloads": -1, "filename": "reltools-0.1.0.tar.gz", "has_sig": false, "md5_digest": "e77c3005eb761e0c47b14c1783c789eb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3783, "upload_time": "2018-08-17T04:58:49", "url": "https://files.pythonhosted.org/packages/4b/2d/2df37c77388a5f4746c7ff34916c71cb8bc096283b36a2779befbae10a9d/reltools-0.1.0.tar.gz" } ], "0.9.0": [ { "comment_text": "", "digests": { "md5": "09ec324a869c3f805615a6d17b55edad", "sha256": "73a4a2ee5b4d33285c6148859dfe619f5212f8da6c6397f3303c8ac9d055a1a0" }, "downloads": -1, "filename": "reltools-0.9.0.tar.gz", "has_sig": false, "md5_digest": "09ec324a869c3f805615a6d17b55edad", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4669, "upload_time": "2018-08-17T07:11:07", "url": "https://files.pythonhosted.org/packages/68/df/3ffbf54f5b1e37150544643b3cfb3afacfd0d249792ee5d285fcb99a29f8/reltools-0.9.0.tar.gz" } ], "0.9.1": [ { "comment_text": "", "digests": { "md5": "de65fdafc0f9e33d200bc78f28aa4d06", "sha256": "f12cf65affc9136323d22207d67239517b0ead82e18c7bc4016a70f81ef962f7" }, "downloads": -1, "filename": "reltools-0.9.1.tar.gz", "has_sig": false, "md5_digest": "de65fdafc0f9e33d200bc78f28aa4d06", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5419, "upload_time": "2018-08-17T09:10:10", "url": "https://files.pythonhosted.org/packages/ec/19/ea388f0ab1b29ba4dea9c6200bd57b3b72f342a3379637156f99ef429f7c/reltools-0.9.1.tar.gz" } ], "0.9.2": [ { "comment_text": "", "digests": { "md5": "6e97318dc2b8d2352b4cf56ed6699608", "sha256": "2ff0720579febcbb29d1953fd3ef5eef296bb93bed5b959754a6a6861f86ad38" }, "downloads": -1, "filename": "reltools-0.9.2.tar.gz", "has_sig": false, "md5_digest": "6e97318dc2b8d2352b4cf56ed6699608", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5504, "upload_time": "2018-08-17T12:46:33", "url": "https://files.pythonhosted.org/packages/6a/6d/30f5f7adbf4d36af5a680567087a42e30f920d95393d9fdf88b45f84b9a4/reltools-0.9.2.tar.gz" } ], "0.9.3": [ { "comment_text": "", "digests": { "md5": "ca78e95ac3d79e52db3bee181debebc3", "sha256": "e23919e0689553efb8a338f011779586130ae31fd37a569c7fce330930644b6c" }, "downloads": -1, "filename": "reltools-0.9.3.tar.gz", "has_sig": false, "md5_digest": "ca78e95ac3d79e52db3bee181debebc3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5795, "upload_time": "2019-07-23T16:43:00", "url": "https://files.pythonhosted.org/packages/77/38/6406e2edec708ed0885535d8dbb35c2db154157357ac0403a46e537741b4/reltools-0.9.3.tar.gz" } ], "0.9.4": [ { "comment_text": "", "digests": { "md5": "3aa65f01a228c8d7a3cb4c9c02a3aac3", "sha256": "6399c68d85180fcb501f878bea7f965486751ee59b83db7128974773bd5406e7" }, "downloads": -1, "filename": "reltools-0.9.4-py3-none-any.whl", "has_sig": false, "md5_digest": "3aa65f01a228c8d7a3cb4c9c02a3aac3", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.5,<4.0", "size": 6830, "upload_time": "2019-08-30T09:03:43", "url": "https://files.pythonhosted.org/packages/03/79/35d87cfe651903c9d5bb1f59f21e985540a95105974bb685113d181a7615/reltools-0.9.4-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "94a52294cf80162877a3edfce54160c8", "sha256": "aaa4b09df7b796f4f7fb6ae67f897308c464a6ad9fcf53d9fd3da32867e1763f" }, "downloads": -1, "filename": "reltools-0.9.4.tar.gz", "has_sig": false, "md5_digest": "94a52294cf80162877a3edfce54160c8", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.5,<4.0", "size": 7728, "upload_time": "2019-08-30T09:03:45", "url": "https://files.pythonhosted.org/packages/4a/c6/0d6210d00d56edaaa5cc878252a4bcc81ecd445c653c0bd2117de6d5f4ab/reltools-0.9.4.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "3aa65f01a228c8d7a3cb4c9c02a3aac3", "sha256": "6399c68d85180fcb501f878bea7f965486751ee59b83db7128974773bd5406e7" }, "downloads": -1, "filename": "reltools-0.9.4-py3-none-any.whl", "has_sig": false, "md5_digest": "3aa65f01a228c8d7a3cb4c9c02a3aac3", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.5,<4.0", "size": 6830, "upload_time": "2019-08-30T09:03:43", "url": "https://files.pythonhosted.org/packages/03/79/35d87cfe651903c9d5bb1f59f21e985540a95105974bb685113d181a7615/reltools-0.9.4-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "94a52294cf80162877a3edfce54160c8", "sha256": "aaa4b09df7b796f4f7fb6ae67f897308c464a6ad9fcf53d9fd3da32867e1763f" }, "downloads": -1, "filename": "reltools-0.9.4.tar.gz", "has_sig": false, "md5_digest": "94a52294cf80162877a3edfce54160c8", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.5,<4.0", "size": 7728, "upload_time": "2019-08-30T09:03:45", "url": "https://files.pythonhosted.org/packages/4a/c6/0d6210d00d56edaaa5cc878252a4bcc81ecd445c653c0bd2117de6d5f4ab/reltools-0.9.4.tar.gz" } ] }