Search code examples
pythonlist-comprehensionordereddictionary

Apply conditional to data being iterated over in list comprehension


I have the following OrderedDict (I'm sorry for the formatting, I can't figure out how to get it to look readable). I basically have an object representing a conversation that sometimes has messages belonging to it and sometimes doesn't.

[OrderedDict([('id', 7), ('members', [OrderedDict([('id', 1), ('username', 'stefan'), ('email', '[email protected]')]), OrderedDict([('id', 10), ('username', 'Angela'), ('email', '[email protected]')])]), ('title', 'Conversation 1'), ('first_member_reveal', True), ('second_member_reveal', True), ('first_member_id', '1'), ('second_member_id', '10'), ('messages', [{'convo_id': 7, 'message': 'Conv 1 message 1', 'created_on': '03.05.2022 17:12:39', 'created_by': 1}])]), OrderedDict([('id', 23), ('members', [OrderedDict([('id', 1), ('username', 'stefan'), ('email', '[email protected]')]), OrderedDict([('id', 11), ('username', 'Sharon'), ('email', '[email protected]')])]), ('title', 'Conversation 8'), ('first_member_reveal', False), ('second_member_reveal', False), ('first_member_id', '1'), ('second_member_id', '11')])]

And I'm applying the following code to it in order to sort the dictionary based on the time at which the latest message belonging to each conversation was created.

sorted_data = sorted(
        serialized_convos.data,
        key=lambda x:
        max(datetime.datetime.strptime(msg['created_on'], '%d.%m.%Y %H:%M:%S') for msg in x['messages'],
        reverse=True)

The code does what I want but as mentioned, there is no 'messages' key in what I'm iterating over in some cases so I get a key error. I tried adding the following conditional in the list comprehension but it isn't working

max(datetime.datetime.strptime(msg['created_on'], '%d.%m.%Y %H:%M:%S') for msg in x['messages'] if 'messages'
    in x.keys())

I also tried adding an if/else conditional before the "for" part of the code and no dice.


Solution

  • If I understand you correctly, you want the conversation without messages move to the back while latest messages are in front.

    You can check if "messages" key is in dictionary and if not, supply some artificial old date. For example:

    sorted_data = sorted(
        data,  # <-- is your data from question
        key=lambda x: max(
            datetime.datetime.strptime(msg["created_on"], "%d.%m.%Y %H:%M:%S")
            for msg in x.get("messages")
        )
        if "messages" in x
        else datetime.datetime(1970, 1, 1),
        reverse=True,
    )
    

    Prints:

    [
        OrderedDict(
            [
                ("id", 7),
                (
                    "members",
                    [
                        OrderedDict(
                            [
                                ("id", 1),
                                ("username", "stefan"),
                                ("email", "[email protected]"),
                            ]
                        ),
                        OrderedDict(
                            [
                                ("id", 10),
                                ("username", "Angela"),
                                ("email", "[email protected]"),
                            ]
                        ),
                    ],
                ),
                ("title", "Conversation 1"),
                ("first_member_reveal", True),
                ("second_member_reveal", True),
                ("first_member_id", "1"),
                ("second_member_id", "10"),
                (
                    "messages",
                    [
                        {
                            "convo_id": 7,
                            "message": "Conv 1 message 1",
                            "created_on": "03.05.2022 17:12:39",
                            "created_by": 1,
                        }
                    ],
                ),
            ]
        ),
        OrderedDict(
            [
                ("id", 23),
                (
                    "members",
                    [
                        OrderedDict(
                            [
                                ("id", 1),
                                ("username", "stefan"),
                                ("email", "[email protected]"),
                            ]
                        ),
                        OrderedDict(
                            [
                                ("id", 11),
                                ("username", "Sharon"),
                                ("email", "[email protected]"),
                            ]
                        ),
                    ],
                ),
                ("title", "Conversation 8"),
                ("first_member_reveal", False),
                ("second_member_reveal", False),
                ("first_member_id", "1"),
                ("second_member_id", "11"),
            ]
        ),
    ]