0

I have the following list of dictionaries:

lines = [
    {
        "attribute": [
            {
                "hello": "world"
            },
            {
                "number": "2.2"
            },
            {
                "this": "that"
            }
        ],
        "subline": [
            {
                "attribute": [
                    {
                        "number": "1"
                    }
                ]
            },
            {
                "attribute": [
                    {
                        "number": "0"
                    }
                ]
            },
            {
                "attribute": [
                    {
                        "number": "5"
                    }
                ]
            }
        ]
    },
    {
        "attribute": [
            {
                "number": "0.2"
            }
        ],
        "subline": []
    },
    {
        "attribute": [],
        "subline": [
            {
                "attribute": [
                    {
                        "number": "20.2"
                    }
                ]
            },
            {
                "attribute": [
                    {
                        "number": "1"
                    },
                    {
                        "data": "15"
                    }
                ]
            }
        ]
    }
]

I would like to sort the list based on the value of the string "number" inside the attribute list inside the list of dictionaries.

Additionally, sort the subline list based on the same criteria (attribute number inside the subline list of dictionaries).

Sometimes the attribute "number" does not exist and sometimes the "subline" list might be empty.

The desired result would be:

lines = [
    {
        "attribute": [
            {
                "number": "0.2"
            }
        ],
        "subline": []
    },
    {
        "attribute": [
            {
                "hello": "world"
            },
            {
                "number": "2.2"
            },
            {
                "this": "that"
            }
        ],
        "subline": [
            {
                "attribute": [
                    {
                        "number": "0"
                    }
                ]
            },
            {
                "attribute": [
                    {
                        "number": "1"
                    }
                ]
            },
            {
                "attribute": [
                    {
                        "number": "5"
                    }
                ]
            }
        ]
    },
    {
        "attribute": [],
        "subline": [
            {
                "attribute": [
                    {
                        "number": "1"
                    },
                    {
                        "data": "15"
                    }
                ]
            },
            {
                "attribute": [
                    {
                        "number": "20.2"
                    }
                ]
            }
        ]
    }
]

EDIT:

Here is how I have solved it:

lines = [{'attribute': [{'hello': 'world'}, {'number': '2.2'}, {'this': 'that'}], 'subline': [{'attribute': [{'number': '1'}]}, {'attribute': [{'number': '0'}]}, {'attribute': [{'number': '5'}]}]}, {'attribute': [{'number': '0.2'}], 'subline': []}, {'attribute': [], 'subline': [{'attribute': [{'number': '20.2'}]}, {'attribute': [{'number': '1'}, {'data': '15'}]}]}]


def getAttributeNumber(lineObject):
    try:
        if isinstance(lineObject.get("subline", []), list):
            if len(lineObject.get("subline", [])) > 0:
                lineObject.get("subline", []).sort(key=lambda o: getAttributeNumber(o))
        if isinstance(lineObject.get("attribute", []), list):
            for attr in lineObject.get("attribute", []):
                if isinstance(attr.get("number"), str):
                    return attr.get("number")
        return "A"
    except Exception:
        return "A"


lines.sort(key=lambda o: getAttributeNumber(o))

What's the most straightforward and perhaps the fastest way to achieve this?

JamesRicky
  • 201
  • 1
  • 3
  • 17
  • Does this answer your question? [How does the key argument in python's sorted function work?](https://stackoverflow.com/questions/32238196/how-does-the-key-argument-in-pythons-sorted-function-work) In your case, the `key` will be `float((x.get("attribute") or [{}])[0].get("number", "inf"))` – Pranav Hosangadi May 25 '21 at 20:17
  • "number" is unfortunately not always the first element in the list, which is what is making this a bit more challenging, do you have a suggestion on how to handle that using the sorted function and the lambda key? – JamesRicky May 25 '21 at 20:43
  • Write a multi-line function that looks for the dict that contains number. You don't have to use a lambda function as the key -- just a function that takes in the elements of the list and returns something that gives its sort order. – Pranav Hosangadi May 25 '21 at 20:56
  • What you've tried? How can we check the method proposed by us is faster than what you already have or not? – Nk03 May 26 '21 at 07:09
  • Yes, I have added a suggestion on how I have solved it, but I am not sure if this is the fastest way to solve this. Any ideas? – JamesRicky May 26 '21 at 21:08

1 Answers1

0

This is how I solved this:

lines = [{'attribute': [{'hello': 'world'}, {'number': '2.2'}, {'this': 'that'}], 'subline': [{'attribute': [{'number': '1'}]}, {'attribute': [{'number': '0'}]}, {'attribute': [{'number': '5'}]}]}, {'attribute': [{'number': '0.2'}], 'subline': []}, {'attribute': [], 'subline': [{'attribute': [{'number': '20.2'}]}, {'attribute': [{'number': '1'}, {'data': '15'}]}]}]


def getAttributeNumber(lineObject):
    try:
        if isinstance(lineObject.get("subline", []), list):
            if len(lineObject.get("subline", [])) > 0:
                lineObject.get("subline", []).sort(key=lambda o: getAttributeNumber(o))
        if isinstance(lineObject.get("attribute", []), list):
            for attr in lineObject.get("attribute", []):
                if isinstance(attr.get("number"), str):
                    return attr.get("number")
        return "A"
    except Exception:
        return "A"


lines.sort(key=lambda o: getAttributeNumber(o))
JamesRicky
  • 201
  • 1
  • 3
  • 17