"Natural sorting" of Pose Libs

I’ve done a really ugly script that sorts the poselib poses alphabetically.
The problem is the sorting method. This is a sorted example :
Pose1
Pose10
Pose11
Pose2
Pose3
Pose4

I’ve been told I need “natural sorting” algorithm, but I’m lost.
Currently the sorting part of my script is this:

import bpy
armaturename='armaturex'  

def str_compare(a,b):
    #a=b -> 0
    #a<b -> 1
    #a>b -> -1
    #if they are the same
    if a==b:
        #print("the same")
        return 0 #returns 0
    
    lena=len(a)
    lenb=len(b)
    count=0
    for count in range(lena):
        if count>=lenb:            
            return -1
        else:        
            if a[count]>b[count]:                
                return -1
            if a[count]<b[count]:
                return 1
    return 1    
            

def compara(a,b):
    if str_compare(a.name.lower(),b.name.lower())==1:       
        name=a.name
        frame=a.frame
        a.name=b.name
        a.frame=b.frame
        b.name=name
        b.frame=frame
    return{'FINISHED'}

class OBJECT_OT_sortlibrary(bpy.types.Operator):
    bl_idname="object.sortlibrary"
    bl_label="Sort the pose library"

            
    def execute(self,context):
        import bpy
        print("Initializing poses sorting")
        #get the time range
        range=bpy.data.actions[bpy.context.object.pose_library.name].frame_range
        start=range[0]
        end=range[1]
        print("The range is from "+str(start )+ " to " +str(end))
        #get pose markers
        frames=[]
        valores=[]
        count=0
        for pmark in bpy.data.actions[bpy.context.object.pose_library.name].pose_markers :            
            print ("Pose: "+str(pmark))
            frames.append(pmark.frame)
            valores.append(str(pmark))
            print("Item " +str(count)+". Frame "+str(frames[count])+" es "+str(valores[count]))
            for pmarkb in bpy.data.actions[bpy.context.object.pose_library.name].pose_markers : 
                if pmark!=pmarkb:
                    compara(pmark,pmarkb)
            count =count+1
       
        return {'FINISHED'}

Note: this is not the full script because it is quite long, this is just the sorting related part. And sorry for the Spanish words in the code.
What should I change for getting a “natural sorting”?

Unfortunately, Python doesn’t have built-in natural sorting.

But you can have a look at:
http://www.codinghorror.com/blog/2007/12/sorting-for-humans-natural-sort-order.html
or
http://code.activestate.com/recipes/285264-natural-string-sorting/

as it happens a while back i wrote little script that pads numbers with zeroes so you get 00001, 00002, 00030, 00400, 05000. which works great if you know in advance the largest number you might see. These of course do sort automatically in the correct order.

all you have to code is a script that looks at the string of the pose name, and starting from the last character stores all the characters that are of type integer when checked.


# given
pose_list = "Pose1", "Pose10", "Pose11", "Pose2", "Pose3", "Pose4"

for pose in pose_list:
    print(pose)

    integers = True
    num_string = ""
    position = -1
    while(integers):
        character = pose[position]
        if character.isdigit():
            position -= 1
            num_string = character + num_string
        else:
            integers = False

    print(num_string)

but it’s not very fast, you might use a match object instead, it keeps the code easier to read :
http://code.google.com/edu/languages/google-python-class/regular-expressions.html


import re

pose_list = "Pose1", "Pose10", "Pose11", "Pose2", "Pose3", "Pose4"
pattern = '\d+'  # one or more numerical characters

for pose in pose_list:
    match = re.search(pattern, pose)
    if match:
        print(match.group())
    else:
        print("no numerical characters in pose name")

this stuff works a treat if you have large sets of objects being created and named and you want them ordered nicely. but if you are simply dealing with a number of poses that you manually name, i’d suggest adding the padding-zeroes yourself. For example sometimes when i’m modeling something i save continuously using filename_001, filename_002…filename_010… etc that way when looking in the file/folders the .blends are in the correct order.

well, this bugged me and i remembered a bit of extra details on the sorted() method, which is you can define your own sort parameters. http://code.google.com/edu/languages/google-python-class/sorting.html

this works but not if your list is inconsistent and has names without numericals you will need additional error checking.


import re

pose_list = "Pose1", "Pose10", "Pose11", "Pose2", "Pose3", "Pose4"
pattern = '\d+'  # one or more numerical characters

def MyFn(pose):
    match = re.search(pattern, pose)
    return int(match.group())

print(sorted(pose_list, key=MyFn))  

>>> ['Pose1', 'Pose2', 'Pose3', 'Pose4', 'Pose10', 'Pose11']

Thank you guys. I’ll give it a new try and if I get something I’ll post it here.