A user has asked this question on here but it was in regards to a list of strings. I have a list of classes and want to modify the answer in this question:
Specifically, this code, works exactly the way I want but I need to modify it to work with class attributes not just a list of strings:
import re
## ref: https://blog.codinghorror.com/sorting-for-humans-natural-sort-order/
def sort_nicely( l ):
""" Sort the given list in the way that humans expect.
"""
convert = lambda text: int(text) if text.isdigit() else text
alphanum_key = lambda key: [ convert(c.replace("_","")) for c in re.split('([0-9] )', key) ]
l.sort( key=alphanum_key )
return print(l)
```
I've tried modifying the lambda expression in many ways but no matter how I modify it I always get the following error:
expected string or bytes-like object
Here is where I am currently at, which does not work. Any insights will be much appreciated
import re
class ContainerTest:
def __init__( self ):
self.name = ''
def sort_nicely( l ):
""" Sort the given list in the way that humans expect.
"""
convert = lambda x: x.name, lambda text: int( x ) if x.isdigit() else x
alphanum_key = lambda key: [ convert( c.replace( "_", "" ) ) for c in re.split( '([0-9] )', key ) ]
l.sort( key=alphanum_key )
return print( l )
items = []
for i in range( 0, 2 ):
item = ContainerTest()
item.name = 'test_128_0' str( i 1 )
items.append( item )
for i in range( 0, 2 ):
item = ContainerTest()
item.name = 'test_64_0' str( i 1 )
items.append( item )
sort_nicely( items )
CodePudding user response:
If you want to sort your ContainerTest
instances by their names (using the logic developed to sort strings), you just need to make the key
function you're sorting with get the attribute from the object it's being passed. The important variable is the key
argument passed to alphanum_key
, which will be the item in the list (an instance of the class, in this case).
Try:
alphanum_key = lambda key: [convert( c.replace("_", ""))
for c in re.split('([0-9] )', key.name)]
The change is at the end of the line, where we do the regex split on key.name
rather than key
.