1

I want to sort naturally, no matter the value, I have found code to do this elsewhere on stack, I just can't incorporate it into what I have,

here's what I have, it sorts the order of the main sublists by the index which the only '0' is in, top right, "sublist[1][3]"

sheet_lists = [[1, ['', '', '', '0']],
           [2, ['', '', '', '1']],
           [3, ['', '', '', '2']],
           [4, ['', '', '', '3']],
           [5, ['', '', '', '4']],
           [6, ['', '', '', '5']],
           [7, ['', '', '', '6']],
           [8, ['', '', '', '7']],
           [9, ['', '', '', '8']],
           [10, ['', '', '', '9']],
           [11, ['', '', '', '10']],
           [12, ['', '', '', '11']],
           [13, ['', '', '', '12']],
           [14, ['', '', '', '13']],
           [15, ['', '', '', '14']],
           [16, ['', '', '', '15']],
           [17, ['', '', '', '16']],
           [18, ['', '', '', '17']]]

sheet_lists.sort(key=lambda lst: lst[1][3], reverse=True)

for l in sheet_lists:
    print (l)

The output this produces is:

[10, ['', '', '', '9']]
[9, ['', '', '', '8']]
[8, ['', '', '', '7']]
[7, ['', '', '', '6']]
[6, ['', '', '', '5']]
[5, ['', '', '', '4']]
[4, ['', '', '', '3']]
[3, ['', '', '', '2']]
[18, ['', '', '', '17']]
[17, ['', '', '', '16']]
[16, ['', '', '', '15']]
[15, ['', '', '', '14']]
[14, ['', '', '', '13']]
[13, ['', '', '', '12']]
[12, ['', '', '', '11']]
[11, ['', '', '', '10']]
[2, ['', '', '', '1']]
[1, ['', '', '', '0']]

I expect:

[18, ['', '', '', '17']]
[17, ['', '', '', '16']]
[16, ['', '', '', '15']]
[15, ['', '', '', '14']]
[14, ['', '', '', '13']]
[13, ['', '', '', '12']]
[12, ['', '', '', '11']]
[11, ['', '', '', '10']]
[10, ['', '', '', '9']]
[9, ['', '', '', '8']]
[8, ['', '', '', '7']]
[7, ['', '', '', '6']]
[6, ['', '', '', '5']]
[5, ['', '', '', '4']]
[4, ['', '', '', '3']]
[3, ['', '', '', '2']]
[2, ['', '', '', '1']]
[1, ['', '', '', '0']]

As you can see, this doesn't sort properly and NOTE: I don't want to simply convert the values to INT or FLOAT before sorting. This is because I anticipate values which include letters or possibly symbols.

Here's the code for naturally sorting a flat list, credit: https://blog.codinghorror.com/sorting-for-humans-natural-sort-order/

import re
def sort_nicely( l ):
    convert = lambda text: int(text) if text.isdigit() else text
    alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ]
    l.sort( key=alphanum_key )

I just can't seem to incorporate it into my function, because I have to call lambda to select a value contained within a sublist inside a list

3
  • What is the output you are getting know and what do you expect it to be Commented Apr 5, 2017 at 15:33
  • you can just change alphanum_key in the code above to pull out the sublist element you want. the sort_nicely will then operate on your specific list. so make that final key the appropriate element so ,key[1][3])] at the end there. Commented Apr 5, 2017 at 15:36
  • If you anticipate letters and symbols you should add some to your sample input and output so that a) people stop telling you to just convert to numbers and b) the kind of sort you want to accomplish is clearer. Commented Apr 5, 2017 at 15:41

2 Answers 2

2

Your key function is:

lambda lst: lst[1][3]

It takes the element to be sorted and, knowing its particular structure, extracts some bit from it to be used as a sorting key. The sorting algorithm you want to use generates a key like this:

alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ]

It takes the element and munges it in some way magical way to achieve what they describe as 'natural' sorting order. You can easily combine the two since in your case, the only change is you don't want the element itself, you want some sub-piece of it. Instead of key in the above (which is equivalent to your lst) you want key[1][3]. So make the change to

alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key[1][3]) ]

Now the magical munging happens on the sub-element you're interested in and sort_nicely works on your particular structure.

Sign up to request clarification or add additional context in comments.

3 Comments

This is correct, thank you, I will accept your answer. As an added question if you know about regular expressions, how would I include negative numbers in the RE here, when I change '1' to '-1' in the sublist it doesn't sort it properly
@new_to_coding that's why i was pestering you for sample data, i don't know what what sort order is 'proper' to you. It's probably worth thinking about exactly what sort order you want - from some of the things you're saying, it almost sounds you really want a multi-field sort rather than the 'human readable' sort in question. Which, if true, would have implications on how you structure your data. If you figure it all out, just ask a new question with whatever you've come up with and the relevant context.
yes you're right, I will come up with some sample data and expected output and ask a new question later, thanks for your help
0

*misread question, leaving up for posterity.

sheet_lists.sort(key=lambda lst: lst[1][3], reverse=True)

Should be

sheet_lists.sort(key=lambda lst: int(lst[1][3]), reverse=True)

String comparisons vs integer

Alternately, you normalize the data to not store the integers as strings.

sheet_lists = [[1, ['', '', '', 0]],
           [2, ['', '', '', 1]],
           [3, ['', '', '', 2]],
           [4, ['', '', '', 3]],
... etc

2 Comments

Question specifically says doesn't want to convert to numbers.
Oop; didn't notice that originally.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.