Home > Software design >  How to sort liberally-deep list of lists and integers?
How to sort liberally-deep list of lists and integers?

Time:10-07

Let's say I have a list like that:

[[5, [2, 1], 3], [3, [8, 7], [2, 1, 3], 2], [[3, 2, 1], 3, -1]]

(each list can store unspecified number of integers and lists in any order). Rules for sorting:

  • integers (if any) should be before any list
  • integers are sorted normally (from lower to higher value)
  • list is "smaller" than another when the first element is lower, if the same we consider the second element, the third, and so on.
  • If the list has the same values as another but less, it's smaller. [1, 2] < [1, 2, 3]

So the final result should be:

[[-1, 3, [1, 2, 3]], [2, 3, [1, 2, 3], [7, 8]], [3, 5, [1, 2]], ]

How to implement that kind of sorting? I've tried to pass recursive function as sort key in sorted, but mostly ended with TypeError (< not supported for int and list).

Another example:

[1, 4, 3, [[5, 7, 1, 2], 2, 5, 10, 2], 8, [2, 5, [5, 3, 3]], [2, 5, 10, 2, [1, 2, 5]]]

After sorting :

[1, 3, 4, 8, [2, 2, 5, 10, [1, 2, 5]], [2, 2, 5, 10, [1, 2, 5, 7]], [2, 5, [3, 3, 5]]]

CodePudding user response:

Quick draft:

def big_brain_sort(li: list) -> list:
    list_with_int = []
    list_with_list = []
    for el in li:
        if isinstance(el, int):
            list_with_int.append(el)
        elif isinstance(el, list):
            list_with_list.append(big_brain_sort(el))
    sorted_list_int = sorted(list_with_int)
    for lista in sorted(list_with_list, key=lambda x: (big_brain_sort(x), len(x))):
        sorted_list_int.append(lista)
    return sorted_list_int

CodePudding user response:

This handles posted test cases plus additional problem ones in comments.

Code

def sort(item):
    if isinstance(item, list):
        # Sort int elements in sublist before list (first element of tuple in key function)
        # Sort int elements in ascending order (second element of tuple in key funciton)
        item = sorted(item, 
                     key = lambda x: (-isinstance(x, int), x if isinstance(x, int) else 0))
        # Recursively sort sublist
        #  - ints are first in ascending order (first element of tuple in key function)
        #  - sublist ordered by the first number in sublist, if the first item is an int (second element of tuple in key function)
        return sorted([sort(x) for x in item], 
                      key = lambda x: (-isinstance(x, int), x[0] if isinstance(x, list) and x else 0))
    else:
        return item

Tests

lst = [[5, [2, 1], 3], [3, [8, 7], [2, 1, 3], 2], [[3, 2, 1], 3, -1]]
print(sort(lst))
>>> [[-1, 3, [1, 2, 3]], [2, 3, [1, 2, 3], [7, 8]], [3, 5, [1, 2]]]

lst = [1, 4, 3, [[5, 7, 1, 2], 2, 5, 10, 2], 8, [2, 5, [5, 3, 3]], [2, 5, 10, 2, [1, 2, 5]]]
print(sort(lst))
>>> [1, 3, 4, 8, [2, 2, 5, 10, [1, 2, 5, 7]], [2, 5, [3, 3, 5]], [2, 2, 5, 10, [1, 2, 5]]]

lst = [[1, 2], [1, [2]]]
print(sort(lst))
>>> [[1, 2], [1, [2]]]

lst = [[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]
print(sort(lst))
>>> [[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]
  • Related