Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Python sort list of dicts by multiple dynamic keys, with None values at last position

I want to sort a list of dicts (dict_list) (that can also contain nested dicts) by a list of received keys (groups).
The values inside the dicts can generally be None.

After sorting, None values should generally be palced in the last position.
Example when i have the following group list and dict list

groups = ["key1", "key3.key4"]
dict_list = [
    {
        "key1": "abc",
        "key2": "def",
        "key3": {
            "key4": "ghi"
        },
        "key5": {
            "key6": "uvw"
        }
    }, 
    {
        "key1": "abc",
        "key2": "asd",
        "key3": {
            "key4": "abc"
        },
        "key5": {
            "key6": "uvw"
        }
    },    
    {
        "key1": None,
        "key2": "asd",
        "key3": {
            "key4": "abc"
        },
        "key5": {
            "key6": "uvw"
        }
    },
    {
        "key1": "abc",
        "key2": None,
        "key3": None,
        "key5": {
            "key6": "uvw"
        }
    },
    {
        "key1": "xyz",
        "key2": None,
        "key3": {
            "key4": "jklm"
        },
        "key5": {
            "key6": "uvw"
        }
    },
    {
        "key1": "abc",
        "key2": "dfd",
        "key3": {
            "key4": "ghi"
        },
        "key5": {
            "key6": "ers"
        }
    }
]

I would expect the following output:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

dict_list = [
    {
        "key1": "abc",
        "key2": "asd",
        "key3": {
            "key4": "abc"
        },
        "key5": {
            "key6": "uvw"
        }
    },
    {
        "key1": "abc",
        "key2": "def",
        "key3": {
            "key4": "ghi"
        },
        "key5": {
            "key6": "uvw"
        }
    },
    {
        "key1": "abc",
        "key2": "dfd",
        "key3": {
            "key4": "ghi"
        },
        "key5": {
            "key6": "ers"
        }
    },
    {
        "key1": "abc",
        "key2": None,
        "key3": None,
        "key5": {
            "key6": "uvw"
        }
    },
    {
        "key1": "xyz",
        "key2": None,
        "key3": {
            "key4": "jklm"
        },
        "key5": {
            "key6": "uvw"
        }
    },
    {
        "key1": None,
        "key2": "asd",
        "key3": {
            "key4": "abc"
        },
        "key5": {
            "key6": "uvw"
        }
    }
]

I tried implementing this using pythons list sort functions and itertools.groupby, but i can’t seem to wrap my head around it.

Thanks in advance!

>Solution :

Try:

def get_values_from_dict(d, keys):
    out = []
    for k in keys:

        root = d
        for kk in k.split("."):
            root = root.get(kk)
            if not root:
                break

        out.append(root)

    return out


def key_function(lst):
    return [(v is None, v) for v in lst]


print(
    sorted(
        dict_list, key=lambda d: key_function(get_values_from_dict(d, groups))
    )
)

Prints:

[
    {
        "key1": "abc",
        "key2": "asd",
        "key3": {"key4": "abc"},
        "key5": {"key6": "uvw"},
    },
    {
        "key1": "abc",
        "key2": "def",
        "key3": {"key4": "ghi"},
        "key5": {"key6": "uvw"},
    },
    {
        "key1": "abc",
        "key2": "dfd",
        "key3": {"key4": "ghi"},
        "key5": {"key6": "ers"},
    },
    {"key1": "abc", "key2": None, "key3": None, "key5": {"key6": "uvw"}},
    {
        "key1": "xyz",
        "key2": None,
        "key3": {"key4": "jklm"},
        "key5": {"key6": "uvw"},
    },
    {
        "key1": None,
        "key2": "asd",
        "key3": {"key4": "abc"},
        "key5": {"key6": "uvw"},
    },
]
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading