{ "info": { "author": "Tidues Wei", "author_email": "tidues@gmail.com", "bugtrack_url": null, "classifiers": [ "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3" ], "description": "# What is Generalized Map Function (generalmap)\nThis is a generalized map function in python, which can lift basic function over various data structures and user defined objects. It implements the idea borrowed from functional programming language, that is to define a simple function first to tackle a small piece of problem, then reuse this function to apply to complicated data structures (sometimes called function lifting).\n\nAn simple example, given `lst=[1, 2, 3]` and function `f = lambda x: x+1`, this functin only focuses on solving the problem for one element in the list, but `map(f, lst)` will apply `f` to a list, which is a more complicated structure. In a nutshell, the map function let you focus on the atom part or essential part of the problem, then reuse the function in a very smart and cheap way.\n\nHowever, the default map function provided by python is very restrictive:\n* it can only apply to iteratable\n* it can cross only **one level** of the structure\n* it is not easy to apply to user defined objects\n\nand these are what generalmap package can do.\n\n# Basic Usage\nSome examples below like applying function to nonhomogeneous data structure are **not good coding styles**, they are simply used to demonstrate what this pacakge can do.\n\n## Lift function automatically\nThis is the default behavior, the gMap function will cross all predefined structures then apply `f` to the **basic types** like `int, float, string` (defaultly) or `int, float` (if set `intoStr=True`). One caveat is that `f` will always apply to the same level of structure.\n\nAn one level example:\n```python\n# define different structures\nsList = [1, 2, 3]\nsTuple = (1, 2, 3)\nsDict = {1: 2, 2: 3, 3: 4}\n\n# create function\nfoo = lambda x: x+1\n\n# create default gMap object\nmp = GMap()\n\n# apply f and print the results\nprint(mp.gMap(foo, sList))\nprint(mp.gMap(foo, sTuple))\nprint(mp.gMap(foo, sDict))\n```\nwith output as:\n```python\n[2, 3, 4]\n(2, 3, 4)\n{1: 3, 2: 4, 3: 5}\n```\n\nExample for two level mixed nonhomogeneous structure:\n```python\nsMixed = [(1, 2), [3, 4, 5], {6: 6, 7: 7}, range(3), slice(None, 10, 2)]\n\ndef foo x:\n return x+1\n\nmp = GMap()\n\nprint(mp.gMap(foo, sMixed))\n```\nwith output as:\n```python\n[(2, 3), [4, 5, 6], {6: 7, 7: 8}, range(1, 4), slice(1, 11, 2)]\n```\nnotice different structures have their own unique lifting behaviors predefined.\n\n\nIn defualt, the gMap will not crossing string to apply function on each character, but this can be changed:\n```python\nsStr1 = '123'\n\nfoo = lambda x: str(int(x)+1)\n\nmp = GMap(intoStr=True) # change default behavior\n\nprint(mp.gMap(foo, sStr1))\n```\nwith output:\n```python\n234\n```\n\n## Lift function by specifying depth\nWith depth specified, gMap will apply `f` to the desinged level without caring whether the type is basic or not. Depth 1 as one level structure (behavior of map function in python).\n\nA example:\n```python\nsMixed = [[(1, 2, 4), (4, 5)], [(6, 7, 8), '91011']]\n\nfoo = lambda x: x[0]\n\nmp = GMap(recDepth=2) # specify depth\n\nprint(mp.gMap(foo, sMixed))\n```\nwith output:\n```python\n[[1, 4], [6, '9']]\n```\nThe `sMixed` has a three-level strucure, but we force gMap only apply to the second level, so the function will take tuples and string as input. Notice we don't need to specify the `intoStr` here, for we don't lift function into the string structure.\n\n## Current supported strucutres\nThe basic (bottom) types including:\n\n`int, float, string`\n\nthe structure types including:\n\n`list, tuple, map, range, slice`\n\nif with `intoStr` set as `True`, then `string` is a structure type instead of basic.\n\n# Advanced Usage: Apply to User Defined Objects\n**This section is not necessary if the basic usage is enough for you!!**\n\nThere are two more things user can achieve with this package:\n1. Register new basic types.\n1. Register new structure types \n\n## Register new basic types\n\nThis can be accomplished by the method `mp.regBasicType(cls)` where `cls` is the class. For instance, suppose there is a new data type `double` defined, and we want it to be a bottom type, so that when we apply gMap automatically, it'll stop and apply `f` on the data of this type. \n\nNotice, if register a new basic type that is already in the structure types, it will be **removed from** the structure type.\n\n## Register new structure types\n\nThe method `mp.regStructType(cls, clsRule)` can register a new structure type, where `cls` is a class and `clsRule` is a rule description function. Same as before, registering an existing basic type to structure type will remove it from the basic type list. \n\nWith new structure type defined, it can be mixed with other structure types to build complicated data structure. And gMap can be used on these objects the way same as before.\n\nBelow is a new data type called MSet (multiset).\n```python\n# a self defined container (multiset)\nclass MSet:\n def __init__(self, lst):\n self.elems = lst\n\n def __repr__(self):\n return('MSet' + str(self.elems) + '')\n\n def __getitem__(self, idx):\n if type(idx) is int:\n return self.elems[idx]\n else:\n return MSet(self.elems[idx])\n\n def toList(self):\n return self.elems\n```\n\nthen we need to define a map rule function for this class, all the rules will be explained in the next section.\n\n```python\n# define the function that describe the map rule\n# each term will be explained in the next section\ndef msetMapRule(mset):\n isBottom = False\n const = MSet\n paramList = mset.toList()\n paramMapIdx = range(len(paramList))\n ifExpand = False\n projFunc = lambda x: x\n liftFunc = lambda x, res: res\n return (isBottom, const, paramList, paramMapIdx, ifExpand, projFunc, liftFunc)\n```\n\nwith both class and rules are defined, we can apply gMap as same as before:\n\n```python\nmp = gMap() # create gMap object\nmp.regStructType(MSet, msetMapRule) # register new structure type with rule\n\n# define functions and data\n# a two level MSet\nmset0 = MSet([1,2])\nmset1 = MSet([3,4])\nmset = MSet([mset0, mset1])\n\n# a tuple of MSets\nmtuple = (MSet([1,2]), MSet([3,4]))\n\n# function to apply\nfoo = lambda x: x+1\n\n# apply and show results\nprint(mp.gMap(foo, mset))\nprint(mp.gMap(foo, mtuple))\n```\nthe output is\n```python\nMSet[MSet[2, 3], MSet[4, 5]]\n(MSet[2, 3], MSet[4, 5])\n```\n\n## The map rule function\nNow suppose we are defining a map rule function `mcMapRule` for the class `MyCls`, then `mcMapRule(myObj)` is a function accepting objects of `MyCls` and ouput a tuple of rules. Each term in the rules are defined as:\n\n1. `isBottom`: a function from the input object `myObj` to bool, to sift extra bottom cases that is input dependent, such as length 1 string is a bottom case for string structure. In most cases, `isBottom = False`.\n\n1. `const`: a construct function that given a list of parameters can construct an object of `MyCls`, not necessary to be the constructor of the class.\n\n1. `paramList`: the list of parameters that used as input for the construct function `const` to produce the input object `myObj`.\n\n1. `paramMapIdx`: the list of indexes of elements in `paramList` that needs to be apply by `f`. In most cases, all parameters needs to be applied by `f`, then `paramMapIdx = range(len(paramList))`.\n\n1. `ifExpand`: means when we apply `const` onto the `paramList`, do we need to expand the list or not. If `const(a,b,c)`, then `ifExpand=True`, if `const([a, b, c])`, then `ifExpand=False`.\n\n1. `projFunc`: define a function that transform the input `myObj` to the next level. **In most cases, there is nothing to transform, so `projFunc = lambda x: x`**. In the dictionary case, we only map `f` on the value instead of the key, so we need to extract the second value to pass to `f`, hence `projFunc = lambda x: x[1]` (in my implementation, the parameter list for dictionary is a list of length 2 tuples, so `x[1]` is extracting the value).\n\n1. `liftFunc`: the reverse process of `projFunc`. After applying `f` on the transformed value we get `res`, then how to merge `res` with current input object `myObj`. **In most cases, there is nothing to merge, so `liftFunc = lambda x, res: res`**. In the dictionary case, we need to combine with key into a tuple, so `liftFunc = lambda x, res: (x[0], res)`.\n\nAn rule of thumb is, if we apply `f` to all the parameters of the construct function, like `list, tuple` or the example `MSet` above, then we always set\n```python\nparaMapIdx = range(len(paramList))\nprojFunc = lambda x: x\nliftFunc = lambda x, res: res\n```\nAnd in most cases `isBottom = False`, so the only things to specify are the construct function, the construct list of parameters and whether or not expand the list when we apply construct function on the parameter list.\n\nAll the rules for the predefined structure types can be found in the source file, can be used as examples for designing rules.\n\n# How to Install\nUse pip\n```python\npip install generalmap\n```\n\n# Future Plan\nAdd more predefined basic and strcutre types.\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/tidues/GeneralizedMapFunction", "keywords": "", "license": "", "maintainer": "", "maintainer_email": "", "name": "generalmap", "package_url": "https://pypi.org/project/generalmap/", "platform": "", "project_url": "https://pypi.org/project/generalmap/", "project_urls": { "Homepage": "https://github.com/tidues/GeneralizedMapFunction" }, "release_url": "https://pypi.org/project/generalmap/1.0.2/", "requires_dist": null, "requires_python": "", "summary": "A generalized map function for lift function over structures", "version": "1.0.2" }, "last_serial": 4078441, "releases": { "1.0.0": [ { "comment_text": "", "digests": { "md5": "dbe05f0da3a14525b2ac6cd3eec51712", "sha256": "ce16c27d92dddc08ee2c7e11db68577c005edc4e3d0884903d9c11c5266be816" }, "downloads": -1, "filename": "generalmap-1.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "dbe05f0da3a14525b2ac6cd3eec51712", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 3723, "upload_time": "2018-07-18T04:02:03", "url": "https://files.pythonhosted.org/packages/9d/62/0a8c1a25404ece5ae8e7e0463e86cd466655f5e551f7877fe3b26aa8a0de/generalmap-1.0.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "c7a5486677f8ef09fe4b5c4710abd155", "sha256": "07ca2385316bca766d7fa01f20e73d27350db5ab2ffa4720ae5eb723b9655926" }, "downloads": -1, "filename": "generalmap-1.0.0.tar.gz", "has_sig": false, "md5_digest": "c7a5486677f8ef09fe4b5c4710abd155", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3208, "upload_time": "2018-07-18T04:02:05", "url": "https://files.pythonhosted.org/packages/4b/f9/ce33712f916a46fd6ca6b049f5d161031c250a14d171582c36d88c9b8948/generalmap-1.0.0.tar.gz" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "0ade3d57f0193f839b361597a41a4027", "sha256": "52e110bdfbfdaf8106b8ad6213340403e34e7b01aeaacdaf29f543fe5cba99e4" }, "downloads": -1, "filename": "generalmap-1.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "0ade3d57f0193f839b361597a41a4027", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 3727, "upload_time": "2018-07-18T04:27:43", "url": "https://files.pythonhosted.org/packages/8f/be/6c3a247c4722f2d1249e540dd2e20c8ecf92ac8bd5dad7f9ad764b143b84/generalmap-1.0.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "b8785e2b5622cf1660bf0fc384c21f51", "sha256": "b43a0ad13be991f54060fc7e816c1b82d4fb80b78fad4b21c9b014ef860a73e4" }, "downloads": -1, "filename": "generalmap-1.0.1.tar.gz", "has_sig": false, "md5_digest": "b8785e2b5622cf1660bf0fc384c21f51", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3215, "upload_time": "2018-07-18T04:27:45", "url": "https://files.pythonhosted.org/packages/1e/63/0ac1b16f0c9eef33b5d8ff53309fa61f42cd59b94571b8bf76e8a27278eb/generalmap-1.0.1.tar.gz" } ], "1.0.2": [ { "comment_text": "", "digests": { "md5": "2a90f61cf6458064d103c503a1c074d9", "sha256": "9dd976b065a7439995e08aa690691fe09da92acc9f28f7207168eba8ac6b0efd" }, "downloads": -1, "filename": "generalmap-1.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "2a90f61cf6458064d103c503a1c074d9", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 7062, "upload_time": "2018-07-18T15:06:12", "url": "https://files.pythonhosted.org/packages/d9/97/0a2836944556142d26fb1143face8245704350e0736cb818ca4431ac3cd3/generalmap-1.0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "2c6000bca84aefabe0df5a93c588a72e", "sha256": "ea2f01510ec8f377afd501b29902f7541c2c0f3ab6267e36850c13823c875257" }, "downloads": -1, "filename": "generalmap-1.0.2.tar.gz", "has_sig": false, "md5_digest": "2c6000bca84aefabe0df5a93c588a72e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7058, "upload_time": "2018-07-18T15:06:13", "url": "https://files.pythonhosted.org/packages/df/d7/02a0eca45bccf0fc6152b8e214e86dbfec4ccb8817edbe49872d3c6ee9c2/generalmap-1.0.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "2a90f61cf6458064d103c503a1c074d9", "sha256": "9dd976b065a7439995e08aa690691fe09da92acc9f28f7207168eba8ac6b0efd" }, "downloads": -1, "filename": "generalmap-1.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "2a90f61cf6458064d103c503a1c074d9", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 7062, "upload_time": "2018-07-18T15:06:12", "url": "https://files.pythonhosted.org/packages/d9/97/0a2836944556142d26fb1143face8245704350e0736cb818ca4431ac3cd3/generalmap-1.0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "2c6000bca84aefabe0df5a93c588a72e", "sha256": "ea2f01510ec8f377afd501b29902f7541c2c0f3ab6267e36850c13823c875257" }, "downloads": -1, "filename": "generalmap-1.0.2.tar.gz", "has_sig": false, "md5_digest": "2c6000bca84aefabe0df5a93c588a72e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7058, "upload_time": "2018-07-18T15:06:13", "url": "https://files.pythonhosted.org/packages/df/d7/02a0eca45bccf0fc6152b8e214e86dbfec4ccb8817edbe49872d3c6ee9c2/generalmap-1.0.2.tar.gz" } ] }