Search code examples
pythonpython-3.xlistsortingtuples

Two level sorting in a nested tuple of nested lists in Python


I have a deeply nested tuple of nested lists as follows:

ip = (array([[[ 50,  73]],
       [[ 50, 107]],
       [[ 55, 108]],
       [[ 55, 121]],
       [[978,  87]],
       [[977,  86]],
       [[977,  73]]], dtype=int32), 

array([[[ 669,    3]],
       [[ 668,    4]],
       [[ 667,    4]],
       [[1033,   71]],
       [[1035,   69]],
       [[1035,    4]],
       [[ 848,    4]],
       [[ 847,    3]],
       [[ 813,    3]],
       [[ 718,    4]],
       [[ 717,    3]]], dtype=int32), 

array([[[ 17,   3]],
       [[ 16,   4]],
       [[  0,   4]],
       [[  0,  49]],
       [[197,  49]],
       [[197,   8]],
       [[ 84,   4]],
       [[ 83,   3]]], dtype=int32))

The length of the main tuple in above example is 3. I want to perform a 2 level sorting on the above structure. First I want to sort all the 3 elements in the main list in increasing order based on the first value of nested list. So in the above case the third element will come first as it has the lowest value of the first element i.e. 0. Second should be the first element as it has the second lowest value of 50and last should be the third element as it has the third lowest value of 1035. The output of the first level sorting should be:

op = (array([[[ 17,   3]],
       [[ 16,   4]],
       [[  0,   4]],
       [[  0,  49]],
       [[197,  49]],
       [[197,   8]],
       [[ 84,   4]],
       [[ 83,   3]]], dtype=int32),

array([[[ 50,  73]],
       [[ 50, 107]],
       [[ 55, 108]],
       [[ 55, 121]],
       [[978,  87]],
       [[977,  86]],
       [[977,  73]]], dtype=int32), 

array([[[ 669,    3]],
       [[ 668,    4]],
       [[ 667,    4]],
       [[1033,   71]],
       [[1035,   69]],
       [[1035,    4]],
       [[ 848,    4]],
       [[ 847,    3]],
       [[ 813,    3]],
       [[ 718,    4]],
       [[ 717,    3]]], dtype=int32), 
)

Now I want to perform the same sorting again on the above op but instead of the first value of the nested list I want to sort based on the second value of the nested list. So now the final output would be as follows:

final_op = (array([[[ 17,   3]],
       [[ 16,   4]],
       [[  0,   4]],
       [[  0,  49]],
       [[197,  49]],
       [[197,   8]],
       [[ 84,   4]],
       [[ 83,   3]]], dtype=int32), 

array([[[ 669,    3]],
       [[ 668,    4]],
       [[ 667,    4]],
       [[1033,   71]],
       [[1035,   69]],
       [[1035,    4]],
       [[ 848,    4]],
       [[ 847,    3]],
       [[ 813,    3]],
       [[ 718,    4]],
       [[ 717,    3]]], dtype=int32),

array([[[ 50,  73]],
       [[ 50, 107]],
       [[ 55, 108]],
       [[ 55, 121]],
       [[978,  87]],
       [[977,  86]],
       [[977,  73]]], dtype=int32)
)

Any help is appreciated!

Thanks in advance!


Solution

  • You can use sorted on your tuple and specify the item using the key parameter

    First sort

    ip = sorted(ip, key=lambda x: x[0][0][0])
    print(ip)
    
    [array([[[ 17,   3]],
           [[ 16,   4]],
           [[  0,   4]],
           [[  0,  49]],
           [[197,  49]],
           [[197,   8]],
           [[ 84,   4]],
           [[ 83,   3]]]),
    array([[[ 50,  73]],
           [[ 50, 107]],
           [[ 55, 108]],
           [[ 55, 121]],
           [[978,  87]],
           [[977,  86]],
           [[977,  73]]]),
    array([[[ 669,    3]],
           [[ 668,    4]],
           [[ 667,    4]],
           [[1033,   71]],
           [[1035,   69]],
           [[1035,    4]],
           [[ 848,    4]],
           [[ 847,    3]],
           [[ 813,    3]],
           [[ 718,    4]],
           [[ 717,    3]]])]
    

    And the second sort

    ip = sorted(ip, key=lambda x: x[0][0][1])
    print(ip)
    
    [array([[[ 17,   3]],
           [[ 16,   4]],
           [[  0,   4]],
           [[  0,  49]],
           [[197,  49]],
           [[197,   8]],
           [[ 84,   4]],
           [[ 83,   3]]]),
    array([[[ 669,    3]],
           [[ 668,    4]],
           [[ 667,    4]],
           [[1033,   71]],
           [[1035,   69]],
           [[1035,    4]],
           [[ 848,    4]],
           [[ 847,    3]],
           [[ 813,    3]],
           [[ 718,    4]],
           [[ 717,    3]]])
    array([[[ 50,  73]],
           [[ 50, 107]],
           [[ 55, 108]],
           [[ 55, 121]],
           [[978,  87]],
           [[977,  86]],
           [[977,  73]]])]
    

    If you want it back as tuple just do tuple(ip)