user8976497
user8976497

Reputation:

Sort list in a numeric order

I plan to sort the following list in a numeric order

In [117]: print(alist)
['1. Introduction', '10. Functional Programming Modules', '11. File and Directory Access',
'12. Data Persistence', '13. Data Compression and Archiving', '14. File Formats', '15. Cryptographic Services', '16. Generic Operating System Services', '17. Concurrent Execution', 
'18. Interprocess Communication and Networking', '19. Internet Data Handling', '2. Built-in Function', '20. Structured Markup Processing Tools', '21. Internet Protocols and Support', '22. Multimedia Services', '23. Internationalization', '24. Program Frameworks', '25. Graphical User Interfaces with Tk', '26. Development Tools', '27. Debugging and Profiling', '28. Software Packaging and Distribution', '29. Python Runtime Services', '3. Built-in Constants', '30. Custom Python Interpreters', '31. Importing Modules', '32. Python Language Services', '33. Miscellaneous Services', '34. MS Windows Specific Services', '35. Unix Specific Services', '36. Superseded Modules', '37. Undocumented Modules', '4. Built-in Types', '5. Built-in Exceptions', '6. Text Processing Services', '7. Binary Data Services', '8. Data Types', '9. Numeric and Mathematical Modules']

I tried sorted, sort(), but get the same result.

The result I desire is

['1.**', '2.**',... '10.**',... '19.**', '20.**'...]

Upvotes: 1

Views: 103

Answers (2)

Ma0
Ma0

Reputation: 15204

You have to pass a key to apply your custom-sort wishes.

res = sorted(alist, key=lambda x: int(x.partition('.')[0]))

What this lambda does is that it takes the strings one-by-one, extracts the value in front of the dot ('.') and converts it to int. Based on that integer value the list is sorted and returned.


Notes:

There are some assumptions built-in to the lambda. If whatever comes before the first dot cannot be cast to int an Error will be thrown. To circumvent that you can use the following, more elaborate, version:

def sort_helper(my_str, str_last=True):
  try:
    return int(my_str.partition('.')[0])  # kudos @JonClements
  except ValueError:
    return float('{}inf'.format({True: '+', False: '-'}[str_last])) # sends malformed inputs to the front or the back depending on the str_last flag

alist = ['1. Introduction', '5. Built-in Exceptions', 'X. Not Implemented Yet']
res = sorted(alist, key=sort_helper)
print(res)  # ['1. Introduction', '5. Built-in Exceptions', 'X. Not Implemented Yet']

or:

res = sorted(alist, key=lambda x: sort_helper(x, False))
print(res)  # ['X. Not Implemented Yet', '1. Introduction', '5. Built-in Exceptions']

Upvotes: 5

timgeb
timgeb

Reputation: 78650

>>> l = ['1. Introduction', '4. End', '2. Chapter 1', '3. Chapter 2']
>>> sorted(l, key=lambda s: int(s[:s.index('.')]))
['1. Introduction', '2. Chapter 1', '3. Chapter 2', '4. End']

Upvotes: 1

Related Questions