0

I need to sort a list containing nested lists based on a condition. The condition is: if first index is 0, sort on index nr 7. Then if second index is 0, sort on index nr 8. So the below list (unsorted):

[[11, 37620, 'mat', 'xxx', 1, 28.5, 0, 11, 37620, 'Arp', 'xxx', 1, 28],
 [10, 24210, 'Skatt', 'xxx', 2, 40, 0, 0, 0, 0, 0, 0, 0],
 [10, 37010, 'test, a', 'xxx', 5, 36.75, 0, 10, 37010, '', 'xxx', 7, 50.75],
 [0, 0, 'mottagare', 'xxx', 3, 20.25, 0, 10, 21511, 0, 0, 0, 0],     
 [10, 40000, 'eld', 'xxx', 5, 30.5, 0, 10, 40000, 'Oly', 'xxx', 5, 30],
 [10, 17060, 'bok', 'xxx', 1, 28.5, 0, 0, 0, 0, 0, 0, 0]]

Should look like this:

[[10, 17060, 'bok', 'xxx', 1, 28.5, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 'mottagare', 'xxx', 3, 20.25, 0, 10, 21511, 0, 0, 0, 0],
 [10, 24210, 'Skatt', 'xxx', 2, 40, 0, 0, 0, 0, 0, 0, 0],
 [10, 40000, 'eld', 'xxx', 5, 30.5, 0, 10, 40000, 'Oly', 'xxx', 5, 30],     
 [10, 37010, 'test, a', 'xxx', 5, 36.75, 0, 10, 37010, '', 'xxx', 7, 50.75],
 [11, 37620, 'mat', 'xxx', 1, 28.5, 0, 11, 37620, 'Arp', 'xxx', 1, 28]]

I have tried with a_list.sort(key = itemgetter(0)) and lambda, but the zero's always end up first. I have solved this by bubble sort, but it is awfully slow already with 6000 elements in the lists. I paste the bubblesort below for reference. The list zero values are originally None, but for sorting in Python 3 I have converted them to int 0.

the_list_pos = 0
for key, value in kund_dict2.items():
    # Start sorting from the whole list, since the_list_pos is zero
    for passnum in range(len(komplett_lista)-1,the_list_pos,-1):
        # Loop the list, one by one
        for i in range(passnum):
            # If these helper variables are None at the end, nothing happens
            comp1 = None
            comp2 = None
            # Check that the variables to compare are not None, and set them to appropiate values
            if komplett_lista[i][0] is not None and komplett_lista[i][0] == key:
                comp1 = komplett_lista[i][1]
            elif komplett_lista[i][7] is not None and komplett_lista[i][7] == key:
                comp1 = komplett_lista[i][8]   
            if komplett_lista[i+1][0] is not None and komplett_lista[i+1][0] == key:
                comp2 = komplett_lista[i+1][1]
            elif komplett_lista[i+1][7] is not None and komplett_lista[i+1][7] == key:
                comp2 = komplett_lista[i+1][8]
            # Do the actual sorting
            if comp1 is not None and comp2 is not None:    
                if comp1 > comp2:
                    temp = komplett_lista[i]
                    komplett_lista[i] = komplett_lista[i+1]
                    komplett_lista[i+1] = temp
    # update the position so that we do not sort over the already sorted data
    the_list_pos += (value)
martineau
  • 119,623
  • 25
  • 170
  • 301
ConSod
  • 743
  • 8
  • 18
  • Conditions like "if komplett_lista[i][0] is not None and" can be simplified to "if komplett_lista[i][0] and" – nicolas.leblanc Oct 18 '16 at 18:40
  • @nicolas.leblanc not necessarily. e.g., you might have a list of `Optional[int]` types where `None` means missing value and `0` is actually a valid value. but in this specific case you might be correct. – acushner Oct 18 '16 at 18:53
  • 1
    Please clarify the exact sorting criteria. Also a possible duplicate of either: [How to sort list of lists](http://stackoverflow.com/q/3121979/923794), and [Sort tuples based on 2nd parameter](http://stackoverflow.com/q/8459231/923794) which shows the use of `itemgetter`, and [how to sort similar values in a sorted list based on second values (iow=tie breaker)](http://stackoverflow.com/q/29551840/923794) – cfi Oct 18 '16 at 19:01

1 Answers1

2

Write a function to contain your logic for finding which column to sort on:

def sort_col_value(row):
    # if first index is 0, sort on index nr 7. 
    if row[0] == 0:
        return row[7]
    # Then if second index is 0, sort on index nr 8
    if row[1] == 0:
        return row[8]
    return row[0]

then use this function as the key parameter:

mylist.sort(key=sort_col_value)
thebjorn
  • 26,297
  • 11
  • 96
  • 138
  • `def sort_col_value(row): if row[0] == 0: return row[7] else: return row[0]` – ConSod Oct 18 '16 at 18:48
  • @ConSod, _return_ operator makes _else_ clause redundant – volcano Oct 18 '16 at 18:51
  • I tried this function above, but the list gets sorted the same as before. Can I return two logical statements or how should I proceed? – ConSod Oct 18 '16 at 18:51
  • There wasn't enough info on what the logic of the comparison was, so you'll have to write that yourself. The general idea is that you write a function that takes a row and returns the value to sort on. – thebjorn Oct 18 '16 at 18:52
  • Thank you! I solved by returning a tuple with the desired conditions. – ConSod Oct 18 '16 at 19:05