{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 集合操作\n",
    "\n",
    "## 构造集合\n",
    "\n",
    "- `numpy.unique(ar, return_index=False, return_inverse=False, return_counts=False, axis=None)` Find the unique elements of an array.\n",
    "    - `return_index=True` 表示返回新列表元素在旧列表中的位置。\n",
    "    - `return_inverse=True`表示返回旧列表元素在新列表中的位置。\n",
    "    - `return_counts=True`表示返回新列表元素在旧列表中出现的次数。\n",
    "    \n",
    "    \n",
    "【例】找出数组中的唯一值并返回已排序的结果。\n",
    "```python\n",
    "import numpy as np\n",
    "\n",
    "x = np.unique([1, 1, 3, 2, 3, 3])\n",
    "print(x)  # [1 2 3]\n",
    "\n",
    "x = sorted(set([1, 1, 3, 2, 3, 3]))\n",
    "print(x)  # [1, 2, 3]\n",
    "\n",
    "x = np.array([[1, 1], [2, 3]])\n",
    "u = np.unique(x)\n",
    "print(u)  # [1 2 3]\n",
    "\n",
    "x = np.array([[1, 0, 0], [1, 0, 0], [2, 3, 4]])\n",
    "y = np.unique(x, axis=0)\n",
    "print(y)\n",
    "# [[1 0 0]\n",
    "#  [2 3 4]]\n",
    "\n",
    "x = np.array(['a', 'b', 'b', 'c', 'a'])\n",
    "u, index = np.unique(x, return_index=True)\n",
    "print(u)  # ['a' 'b' 'c']\n",
    "print(index)  # [0 1 3]\n",
    "print(x[index])  # ['a' 'b' 'c']\n",
    "\n",
    "x = np.array([1, 2, 6, 4, 2, 3, 2])\n",
    "u, index = np.unique(x, return_inverse=True)\n",
    "print(u)  # [1 2 3 4 6]\n",
    "print(index)  # [0 1 4 3 1 2 1]\n",
    "print(u[index])  # [1 2 6 4 2 3 2]\n",
    "\n",
    "u, count = np.unique(x, return_counts=True)\n",
    "print(u)  # [1 2 3 4 6]\n",
    "print(count)  # [1 3 1 1 1]\n",
    "```\n",
    "\n",
    "## 布尔运算\n",
    "\n",
    "- `numpy.in1d(ar1, ar2, assume_unique=False, invert=False)` Test whether each element of a 1-D array is also present in a second array.\n",
    "\n",
    "Returns a boolean array the same length as `ar1` that is True where an element of `ar1` is in `ar2` and False otherwise.\n",
    "\n",
    "【例】前面的数组是否包含于后面的数组，返回布尔值。返回的值是针对第一个参数的数组的，所以维数和第一个参数一致，布尔值与数组的元素位置也一一对应。\n",
    "```python\n",
    "import numpy as np\n",
    "\n",
    "test = np.array([0, 1, 2, 5, 0])\n",
    "states = [0, 2]\n",
    "mask = np.in1d(test, states)\n",
    "print(mask)  # [ True False  True False  True]\n",
    "print(test[mask])  # [0 2 0]\n",
    "\n",
    "mask = np.in1d(test, states, invert=True)\n",
    "print(mask)  # [False  True False  True False]\n",
    "print(test[mask])  # [1 5]\n",
    "```\n",
    "\n",
    "\n",
    "### 求两个集合的交集：\n",
    "\n",
    "- `numpy.intersect1d(ar1, ar2, assume_unique=False, return_indices=False)` Find the intersection of two arrays.\n",
    "\n",
    "Return the sorted, unique values that are in both of the input arrays.\n",
    "\n",
    "【例】求两个数组的唯一化+求交集+排序函数。\n",
    "```python\n",
    "import numpy as np\n",
    "from functools import reduce\n",
    "\n",
    "x = np.intersect1d([1, 3, 4, 3], [3, 1, 2, 1])\n",
    "print(x)  # [1 3]\n",
    "\n",
    "x = np.array([1, 1, 2, 3, 4])\n",
    "y = np.array([2, 1, 4, 6])\n",
    "xy, x_ind, y_ind = np.intersect1d(x, y, return_indices=True)\n",
    "print(x_ind)  # [0 2 4]\n",
    "print(y_ind)  # [1 0 2]\n",
    "print(xy)  # [1 2 4]\n",
    "print(x[x_ind])  # [1 2 4]\n",
    "print(y[y_ind])  # [1 2 4]\n",
    "\n",
    "x = reduce(np.intersect1d, ([1, 3, 4, 3], [3, 1, 2, 1], [6, 3, 4, 2]))\n",
    "print(x)  # [3]\n",
    "```\n",
    "\n",
    "### 求两个集合的并集：\n",
    "\n",
    "- `numpy.union1d(ar1, ar2)` Find the union of two arrays.\n",
    "\n",
    "Return the unique, sorted array of values that are in either of the two input arrays.\n",
    "\n",
    "【例】计算两个集合的并集，唯一化并排序。\n",
    "```python\n",
    "import numpy as np\n",
    "from functools import reduce\n",
    "\n",
    "x = np.union1d([-1, 0, 1], [-2, 0, 2])\n",
    "print(x)  # [-2 -1  0  1  2]\n",
    "x = reduce(np.union1d, ([1, 3, 4, 3], [3, 1, 2, 1], [6, 3, 4, 2]))\n",
    "print(x)  # [1 2 3 4 6]\n",
    "'''\n",
    "functools.reduce(function, iterable[, initializer])\n",
    "将两个参数的 function 从左至右积累地应用到 iterable 的条目，以便将该可迭代对象缩减为单一的值。 例如，reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) 是计算 ((((1+2)+3)+4)+5) 的值。 左边的参数 x 是积累值而右边的参数 y 则是来自 iterable 的更新值。 如果存在可选项 initializer，它会被放在参与计算的可迭代对象的条目之前，并在可迭代对象为空时作为默认值。 如果没有给出 initializer 并且 iterable 仅包含一个条目，则将返回第一项。\n",
    "\n",
    "大致相当于：\n",
    "def reduce(function, iterable, initializer=None):\n",
    "    it = iter(iterable)\n",
    "    if initializer is None:\n",
    "        value = next(it)\n",
    "    else:\n",
    "        value = initializer\n",
    "    for element in it:\n",
    "        value = function(value, element)\n",
    "    return value\n",
    "'''\n",
    "```\n",
    "\n",
    "### 求两个集合的差集：\n",
    "\n",
    "- `numpy.setdiff1d(ar1, ar2, assume_unique=False)` Find the set difference of two arrays.\n",
    "\n",
    "\n",
    "Return the unique values in `ar1` that are not in `ar2`.\n",
    "\n",
    "【例】集合的差，即元素存在于第一个函数不存在于第二个函数中。\n",
    "```python\n",
    "import numpy as np\n",
    "\n",
    "a = np.array([1, 2, 3, 2, 4, 1])\n",
    "b = np.array([3, 4, 5, 6])\n",
    "x = np.setdiff1d(a, b)\n",
    "print(x)  # [1 2]\n",
    "```\n",
    "\n",
    "### 求两个集合的异或：\n",
    "\n",
    "- `setxor1d(ar1, ar2, assume_unique=False)` Find the set exclusive-or of two arrays.\n",
    "\n",
    "【例】集合的对称差，即两个集合的交集的补集。简言之，就是两个数组中各自独自拥有的元素的集合。\n",
    "\n",
    "```python\n",
    "import numpy as np\n",
    "\n",
    "a = np.array([1, 2, 3, 2, 4, 1])\n",
    "b = np.array([3, 4, 5, 6])\n",
    "x = np.setxor1d(a, b)\n",
    "print(x)  # [1 2 5 6]\n",
    "```\n",
    "\n",
    "\n",
    "\n",
    "---\n",
    "**参考文献**\n",
    "- https://www.jianshu.com/p/3bfe21aa1adb\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python35",
   "language": "python",
   "name": "python35"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.10"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {
    "height": "calc(100% - 180px)",
    "left": "10px",
    "top": "150px",
    "width": "279.176px"
   },
   "toc_section_display": true,
   "toc_window_display": true
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
