Numerically order a list based on a pattern
<p>I have a list of file names in the form:</p>

<pre><code>['comm_1_1.txt', 'comm_1_10.txt', 'comm_1_11.txt', 'comm_1_4.txt', 'comm_1_5.txt', 'comm_1_6.txt']
</code></pre>

<p>I wonder how to sort this list numerically to obtain the output:</p>

<pre><code>['comm_1_1.txt', 'comm_1_4.txt', 'comm_1_5.txt', 'comm_1_6.txt', 'comm_1_10.txt', 'comm_1_11.txt']
</code></pre>

<p>One technique used for this kind of "human sorting" is to split keys to tuples and convert numeric parts to actual numbers:</p>

<pre><code>ss = ['comm_1_1.txt', 'comm_1_10.txt', 'comm_1_11.txt', 'comm_1_4.txt', 'comm_1_5.txt', 'comm_1_6.txt']

print(sorted(ss, key=lambda x : map((lambda v: int(v) if "0" &lt;= v[0] &lt;= "9" else v), re.findall("[0-9]+|[^0-9]+", x))))
</code></pre>

<p>or, more readable</p>

<pre><code>def sortval(x):
   if "0" &lt;= x &lt;= "9":
       return int(x)
   else:
       return x

def human_sort_key(x):
   return map(sortval, re.findall("[0-9]+|[^0-9]+", x))

print sorted(ss, key=human_sort_key)
</code></pre>

<p>the idea is to split between numeric and non-numeric parts and placing the parts in a list after converting the numeric parts to actual numbers (so that <code>10</code> comes after <code>2</code>).</p>

<p>Lexicographically sorting the lists gives the expected result.</p>

python sorting