<p>这是基于Ajax1234的答案。它避免了答案的冗余计算。而不是通过等价关系进行递归分区。这并不意味着歧视。这将成本从<code>N**2/2</code>调用<code>is_match</code>降低到只<code>N</code>调用<code>key</code>。<code>key</code>使用<code>None</code>作为文件名中数字部分的通配符。你知道吗</p>
<pre><code>import re
from collections import defaultdict
def key(v):
return tuple(None if p.isdigit() else p for p in re.sub('.dat$', '', v).split())
def partition(l, key=None):
d = defaultdict(list)
for e in l:
k = key(e) if key is not None else e
d[k].append(e)
return [d[k] for k in sorted(d)]
partition(filter(None, _input.split('\n')), key=key)
</code></pre>
<p>这将导致:</p>
<pre><code>[['ABC 956.dat', 'ABC 114.dat', 'ABC 577.dat', 'ABC 782.dat'],
['ABC 127 JKL.dat', 'ABC 272 JKL.dat', 'ABC 462 JKL.dat', 'ABC 707 JKL.dat'],
['ABC 258 PQR0 0.dat', 'ABC 551 PQR0 3.dat', 'ABC 606 PQR0 5.dat', 'ABC 654 PQR0 2.dat'],
['ABC 542 PQR1 4.dat', 'ABC 234 PQR1 2.dat', 'ABC 432 PQR1 7.dat', 'ABC 766 PQR1 5.dat'],
['ABC 137 XYZ 97.dat', 'ABC 164 XYZ 25.dat', 'ABC 418 XYZ 13.dat', 'ABC 913 XYZ 11.dat'],
['ABC DEF 10.dat', 'ABC DEF 23.dat', 'ABC DEF 27.dat', 'ABC DEF 54.dat'],
['XYZ-ABC 158.dat', 'XYZ-ABC 221.dat', 'XYZ-ABC 668.dat', 'XYZ-ABC 919.dat']]
</code></pre>
<hr/>
<p>我似乎还不太清楚该在哪里做出改变:</p>
<pre><code>def key(v):
return tuple(None if p.isdigit() else p for p in re.sub('.dat$', '', v).split('_'))
partition(filter(None, input_list), key=key)
</code></pre>