|
18 | 18 | "#|export\n",
|
19 | 19 | "from fastcore.imports import *\n",
|
20 | 20 | "import ast,builtins,pprint,types,typing\n",
|
| 21 | + "from functools import cmp_to_key\n", |
21 | 22 | "from copy import copy\n",
|
22 | 23 | "from datetime import date\n",
|
23 | 24 | "try: from types import UnionType\n",
|
|
671 | 672 | "execution_count": null,
|
672 | 673 | "metadata": {},
|
673 | 674 | "outputs": [
|
| 675 | + { |
| 676 | + "name": "stderr", |
| 677 | + "output_type": "stream", |
| 678 | + "text": [ |
| 679 | + "/Users/jhoward/miniforge3/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", |
| 680 | + " from .autonotebook import tqdm as notebook_tqdm\n" |
| 681 | + ] |
| 682 | + }, |
674 | 683 | {
|
675 | 684 | "data": {
|
676 | 685 | "text/markdown": [
|
677 | 686 | "---\n",
|
678 | 687 | "\n",
|
679 |
| - "[source](https://github.com/fastai/fastcore/blob/master/fastcore/basics.py#L113){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", |
| 688 | + "[source](https://github.com/AnswerDotAI/fastcore/blob/master/fastcore/basics.py#L113){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", |
680 | 689 | "\n",
|
681 | 690 | "### get_class\n",
|
682 | 691 | "\n",
|
|
688 | 697 | "text/plain": [
|
689 | 698 | "---\n",
|
690 | 699 | "\n",
|
691 |
| - "[source](https://github.com/fastai/fastcore/blob/master/fastcore/basics.py#L113){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", |
| 700 | + "[source](https://github.com/AnswerDotAI/fastcore/blob/master/fastcore/basics.py#L113){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", |
692 | 701 | "\n",
|
693 | 702 | "### get_class\n",
|
694 | 703 | "\n",
|
|
866 | 875 | "text/markdown": [
|
867 | 876 | "---\n",
|
868 | 877 | "\n",
|
869 |
| - "[source](https://github.com/fastai/fastcore/blob/master/fastcore/basics.py#L157){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", |
| 878 | + "[source](https://github.com/AnswerDotAI/fastcore/blob/master/fastcore/basics.py#L157){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", |
870 | 879 | "\n",
|
871 | 880 | "#### ignore_exceptions\n",
|
872 | 881 | "\n",
|
|
877 | 886 | "text/plain": [
|
878 | 887 | "---\n",
|
879 | 888 | "\n",
|
880 |
| - "[source](https://github.com/fastai/fastcore/blob/master/fastcore/basics.py#L157){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", |
| 889 | + "[source](https://github.com/AnswerDotAI/fastcore/blob/master/fastcore/basics.py#L157){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", |
881 | 890 | "\n",
|
882 | 891 | "#### ignore_exceptions\n",
|
883 | 892 | "\n",
|
|
2901 | 2910 | "text/markdown": [
|
2902 | 2911 | "---\n",
|
2903 | 2912 | "\n",
|
2904 |
| - "[source](https://github.com/fastai/fastcore/blob/master/fastcore/basics.py#L524){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", |
| 2913 | + "[source](https://github.com/AnswerDotAI/fastcore/blob/master/fastcore/basics.py#L524){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", |
2905 | 2914 | "\n",
|
2906 | 2915 | "#### GetAttr\n",
|
2907 | 2916 | "\n",
|
|
2912 | 2921 | "text/plain": [
|
2913 | 2922 | "---\n",
|
2914 | 2923 | "\n",
|
2915 |
| - "[source](https://github.com/fastai/fastcore/blob/master/fastcore/basics.py#L524){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", |
| 2924 | + "[source](https://github.com/AnswerDotAI/fastcore/blob/master/fastcore/basics.py#L524){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", |
2916 | 2925 | "\n",
|
2917 | 2926 | "#### GetAttr\n",
|
2918 | 2927 | "\n",
|
|
3833 | 3842 | "outputs": [],
|
3834 | 3843 | "source": [
|
3835 | 3844 | "#|export\n",
|
3836 |
| - "def sorted_ex(iterable, key=None, reverse=False):\n", |
3837 |
| - " \"Like `sorted`, but if key is str use `attrgetter`; if int use `itemgetter`\"\n", |
3838 |
| - " if isinstance(key,str): k=lambda o:getattr(o,key,0)\n", |
| 3845 | + "def sorted_ex(iterable, key=None, reverse=False, cmp=None, **kwargs):\n", |
| 3846 | + " \"Like `sorted`, but if key is str use `attrgetter`; if int use `itemgetter`; use `cmp` comparator function or `key` with `kwargs`\"\n", |
| 3847 | + " if callable(key) and kwargs: k=partial(key, **kwargs)\n", |
| 3848 | + " elif callable(cmp):\n", |
| 3849 | + " if kwargs: cmp=partial(cmp, **kwargs)\n", |
| 3850 | + " k = cmp_to_key(cmp)\n", |
| 3851 | + " elif isinstance(key,str): k=lambda o:getattr(o,key,0)\n", |
3839 | 3852 | " elif isinstance(key,int): k=itemgetter(key)\n",
|
3840 | 3853 | " else: k=key\n",
|
3841 | 3854 | " return sorted(iterable, key=k, reverse=reverse)"
|
3842 | 3855 | ]
|
3843 | 3856 | },
|
| 3857 | + { |
| 3858 | + "cell_type": "markdown", |
| 3859 | + "metadata": {}, |
| 3860 | + "source": [ |
| 3861 | + "Attributes can be used for sorting by passing their name as a string:" |
| 3862 | + ] |
| 3863 | + }, |
| 3864 | + { |
| 3865 | + "cell_type": "code", |
| 3866 | + "execution_count": null, |
| 3867 | + "metadata": {}, |
| 3868 | + "outputs": [], |
| 3869 | + "source": [ |
| 3870 | + "class TestObj:\n", |
| 3871 | + " def __init__(self, x): self.x = x\n", |
| 3872 | + "objs = [TestObj(i) for i in [3,1,2]]\n", |
| 3873 | + "test_eq([o.x for o in sorted_ex(objs, 'x')], [1,2,3])" |
| 3874 | + ] |
| 3875 | + }, |
| 3876 | + { |
| 3877 | + "cell_type": "markdown", |
| 3878 | + "metadata": {}, |
| 3879 | + "source": [ |
| 3880 | + "Tuple/list items can be sorted by index position:" |
| 3881 | + ] |
| 3882 | + }, |
| 3883 | + { |
| 3884 | + "cell_type": "code", |
| 3885 | + "execution_count": null, |
| 3886 | + "metadata": {}, |
| 3887 | + "outputs": [], |
| 3888 | + "source": [ |
| 3889 | + "items = [(1,'c'), (2,'b'), (3,'a')]\n", |
| 3890 | + "test_eq(sorted_ex(items, 1), [(3,'a'), (2,'b'), (1,'c')])" |
| 3891 | + ] |
| 3892 | + }, |
| 3893 | + { |
| 3894 | + "cell_type": "markdown", |
| 3895 | + "metadata": {}, |
| 3896 | + "source": [ |
| 3897 | + "A custom key function transforms values:" |
| 3898 | + ] |
| 3899 | + }, |
| 3900 | + { |
| 3901 | + "cell_type": "code", |
| 3902 | + "execution_count": null, |
| 3903 | + "metadata": {}, |
| 3904 | + "outputs": [], |
| 3905 | + "source": [ |
| 3906 | + "test_eq(sorted_ex([3,1,2], lambda x: -x), [3,2,1])" |
| 3907 | + ] |
| 3908 | + }, |
| 3909 | + { |
| 3910 | + "cell_type": "markdown", |
| 3911 | + "metadata": {}, |
| 3912 | + "source": [ |
| 3913 | + "You can use a comparison function (returning -1/1/0):" |
| 3914 | + ] |
| 3915 | + }, |
| 3916 | + { |
| 3917 | + "cell_type": "code", |
| 3918 | + "execution_count": null, |
| 3919 | + "metadata": {}, |
| 3920 | + "outputs": [], |
| 3921 | + "source": [ |
| 3922 | + "test_eq(sorted_ex([3,1,2], cmp=lambda a,b: 1 if a>b else -1 if a<b else 0), [1,2,3])" |
| 3923 | + ] |
| 3924 | + }, |
| 3925 | + { |
| 3926 | + "cell_type": "markdown", |
| 3927 | + "metadata": {}, |
| 3928 | + "source": [ |
| 3929 | + "Additional parameters can be passed to key/cmp functions:" |
| 3930 | + ] |
| 3931 | + }, |
| 3932 | + { |
| 3933 | + "cell_type": "code", |
| 3934 | + "execution_count": null, |
| 3935 | + "metadata": {}, |
| 3936 | + "outputs": [], |
| 3937 | + "source": [ |
| 3938 | + "def key_with_kwargs(x, offset=0): return x + offset\n", |
| 3939 | + "test_eq(sorted_ex([3,1,2], key=key_with_kwargs, offset=10), [1,2,3])" |
| 3940 | + ] |
| 3941 | + }, |
| 3942 | + { |
| 3943 | + "cell_type": "markdown", |
| 3944 | + "metadata": {}, |
| 3945 | + "source": [ |
| 3946 | + "Reverse sort capability:" |
| 3947 | + ] |
| 3948 | + }, |
| 3949 | + { |
| 3950 | + "cell_type": "code", |
| 3951 | + "execution_count": null, |
| 3952 | + "metadata": {}, |
| 3953 | + "outputs": [], |
| 3954 | + "source": [ |
| 3955 | + "test_eq(sorted_ex([1,2,3], reverse=True), [3,2,1])" |
| 3956 | + ] |
| 3957 | + }, |
3844 | 3958 | {
|
3845 | 3959 | "cell_type": "code",
|
3846 | 3960 | "execution_count": null,
|
|
0 commit comments