Sorting dict items by key, beyond alphanumeric sorting
<p>I have written this code:</p>

<pre><code>n=5
dizN={}
for q in range(0,n+1):
    h=n-q
    dizN['a'+str(q)+'p'+str(h)]=0
</code></pre>

<p>that creates such a dictionary:</p>

<p>dizN</p>

<pre><code>Out[120]: {'a0p5': 0, 'a1p4': 0, 'a2p3': 0, 'a3p2': 0, 'a4p1': 0, 'a5p0': 0}
</code></pre>

<p>Note that "n" is the basic parameter for my code. As you can see, the sum of integers present in dict keys string is always =n (=5 in this case, where n=5).</p>

<p>It is important for me (for more difficult purposes in my program) that, for every n anyone can choose, the dict is ordered in this way: </p>

<pre><code>{'a0p(n)': 0, 'a1p(n-1)': 0, ....., 'a(n-1)p1': 0, 'a(n)p0': 0}
</code></pre>

<p>My code is ok, but only for n&lt;10. 
    If n is >=10, this is what happens: (n=12) dizN:</p>

<pre><code>Out[121]: 
  {'a0p12': 0,
   'a10p2': 0,
   'a11p1': 0,
   'a12p0': 0,
   'a1p11': 0,
   'a2p10': 0,
   'a3p9': 0,
   'a4p8': 0,
   'a5p7': 0,
   'a6p6': 0,
   'a7p5': 0,
   'a8p4': 0,
   'a9p3': 0}
</code></pre>

<p>As you can see the interpreter follows alphanumeric sorting;</p>

<p>Anybody know if there is a way to obtain the same dict sorted this way:</p>

<pre><code>{'a0p12': 0,
 'a1p11': 0,
 'a2p10': 0,
 'a3p9': 0,
 'a4p8': 0,
 'a5p7': 0,
 'a6p6': 0,
 'a7p5': 0,
 'a8p4': 0,
 'a9p3': 0,
 'a10p2': 0,
 'a11p1': 0,
 'a12p0': 0}
</code></pre>

<p>?</p>

<p>I know that dictionaries are basically non sortable, but i hope somebody knows some trick to obtain my purpose anyway :)</p>

<p>Thanks a lot!</p>

<p><em>dicts</em> are <em>unordered</em>, so to get the order you are going to have to sort the items and use an <em>OrderedDict</em> to maintain the sorted order. To get the order you want you can create tuples from the groups of integers so you sort as integers in lexicographical order:</p>

<pre><code>from itertools import groupby
from collections import OrderedDict
d = {'a0p12': 0, 'a10p2': 0, 'a11p1': 0, 'a12p0': 0, 'a1p11': 0, 'a2p10': 0,
     'a3p9': 0, 'a4p8': 0, 'a5p7': 0, 'a6p6': 0, 'a7p5': 0, 'a8p4': 0, 'a9p3': 0}

def key_func(x):
    """'a0p12' -&gt; (0, 12)"""
    return tuple(int("".join(v)) for k,v in groupby(x[0], key=str.isdigit) if k)
od = OrderedDict(sorted(d.items(), key=key_func))

print(od)
</code></pre>

<p>Which would give you:</p>

<pre><code>OrderedDict([('a0p12', 0), ('a1p11', 0), ('a2p10', 0), ('a3p9', 0), 
('a4p8', 0), ('a5p7', 0), ('a6p6', 0), ('a7p5', 0), ('a8p4', 0), 
('a9p3', 0), ('a10p2', 0), ('a11p1', 0), ('a12p0', 0)])
</code></pre>

<p>You could also use a <em>regex</em> to find the groups of digits:</p>

<pre><code>from collections import OrderedDict
import re

d = {'a0p12': 0, 'a10p2': 0, 'a11p1': 0, 'a12p0': 0, 'a1p11': 0, 'a2p10': 0,
     'a3p9': 0, 'a4p8': 0, 'a5p7': 0, 'a6p6': 0, 'a7p5': 0, 'a8p4': 0, 'a9p3': 0}



def key_func(x,patt=re.compile("\d+")):
    """'a0p12' -&gt; (0, 12)"""
    return tuple(map(int, patt.findall(x[0])))

od = OrderedDict(sorted(d.items(), key=key_func))

print(od)
</code></pre>

python sorting dictionary tuples