有時候需要将檔案名按照數字大小排序,而不是按照字母順序排序,例如:
Traditional Sort
Alphanum
在Windows XP及以後的系統中,通過修改系統資料庫,或者使用組政策(實質上還是修改系統資料庫),可以控制使用哪種排序方式,進行檔案名排序。在
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer下面建立
DWORD鍵:NoStrCmpLogical,然後設定值為1,禁止使用智能排序;設定為0,啟用智能排序。
程式實作智能排序,有人已經寫了,在這轉一下C#實作。最後的參考清單中的網址上,有各種語言的實作方法。
<code>/*</code>
<code> </code><code>* The Alphanum Algorithm is an improved sorting algorithm for strings</code>
<code> </code><code>* containing numbers. Instead of sorting numbers in ASCII order like</code>
<code> </code><code>* a standard sort, this algorithm sorts numbers in numeric order.</code>
<code> </code><code>*</code>
<code> </code><code>* The Alphanum Algorithm is discussed at http://www.DaveKoelle.com</code>
<code> </code><code>* Based on the Java implementation of Dave Koelle's Alphanum algorithm.</code>
<code> </code><code>* Contributed by Jonathan Ruckwood <[email protected]></code>
<code> </code><code>* Adapted by Dominik Hurnaus <[email protected]> to</code>
<code> </code><code>* - correctly sort words where one word starts with another word</code>
<code> </code><code>* - have slightly better performance</code>
<code> </code><code>* This library is free software; you can redistribute it and/or</code>
<code> </code><code>* modify it under the terms of the GNU Lesser General Public</code>
<code> </code><code>* License as published by the Free Software Foundation; either</code>
<code> </code><code>* version 2.1 of the License, or any later version.</code>
<code> </code><code>* This library is distributed in the hope that it will be useful,</code>
<code> </code><code>* but WITHOUT ANY WARRANTY; without even the implied warranty of</code>
<code> </code><code>* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU</code>
<code> </code><code>* Lesser General Public License for more details.</code>
<code> </code><code>* You should have received a copy of the GNU Lesser General Public</code>
<code> </code><code>* License along with this library; if not, write to the Free Software</code>
<code> </code><code>* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA</code>
<code> </code><code>*/</code>
<code>using</code> <code>System;</code>
<code>using</code> <code>System.Collections;</code>
<code>using</code> <code>System.Text;</code>
<code> </code><code>* Please compare against the latest Java version at http://www.DaveKoelle.com</code>
<code> </code><code>* to see the most recent modifications</code>
<code>namespace</code> <code>AlphanumComparator</code>
<code>{</code>
<code> </code><code>public</code> <code>class</code> <code>AlphanumComparator : IComparer</code>
<code> </code><code>{</code>
<code> </code><code>private</code> <code>enum</code> <code>ChunkType {Alphanumeric, Numeric};</code>
<code> </code><code>private</code> <code>bool</code> <code>InChunk(</code><code>char</code> <code>ch, </code><code>char</code> <code>otherCh)</code>
<code> </code><code>{</code>
<code> </code><code>ChunkType type = ChunkType.Alphanumeric;</code>
<code> </code><code>if</code> <code>(</code><code>char</code><code>.IsDigit(otherCh))</code>
<code> </code><code>{</code>
<code> </code><code>type = ChunkType.Numeric;</code>
<code> </code><code>}</code>
<code> </code><code>if</code> <code>((type == ChunkType.Alphanumeric && </code><code>char</code><code>.IsDigit(ch))</code>
<code> </code><code>|| (type == ChunkType.Numeric && !</code><code>char</code><code>.IsDigit(ch)))</code>
<code> </code><code>return</code> <code>false</code><code>;</code>
<code> </code><code>return</code> <code>true</code><code>;</code>
<code> </code><code>}</code>
<code> </code><code>public</code> <code>int</code> <code>Compare(</code><code>object</code> <code>x, </code><code>object</code> <code>y)</code>
<code> </code><code>String s1 = x </code><code>as</code> <code>string</code><code>;</code>
<code> </code><code>String s2 = y </code><code>as</code> <code>string</code><code>;</code>
<code> </code><code>if</code> <code>(s1 == </code><code>null</code> <code>|| s2 == </code><code>null</code><code>)</code>
<code> </code><code>return</code> <code>0;</code>
<code> </code><code>int</code> <code>thisMarker = 0, thisNumericChunk = 0;</code>
<code> </code><code>int</code> <code>thatMarker = 0, thatNumericChunk = 0;</code>
<code> </code><code>while</code> <code>((thisMarker < s1.Length) || (thatMarker < s2.Length))</code>
<code> </code><code>if</code> <code>(thisMarker >= s1.Length)</code>
<code> </code><code>{</code>
<code> </code><code>return</code> <code>-1;</code>
<code> </code><code>}</code>
<code> </code><code>else</code> <code>if</code> <code>(thatMarker >= s2.Length)</code>
<code> </code><code>return</code> <code>1;</code>
<code> </code><code>char</code> <code>thisCh = s1[thisMarker];</code>
<code> </code><code>char</code> <code>thatCh = s2[thatMarker];</code>
<code> </code><code>StringBuilder thisChunk = </code><code>new</code> <code>StringBuilder();</code>
<code> </code><code>StringBuilder thatChunk = </code><code>new</code> <code>StringBuilder();</code>
<code> </code><code>while</code> <code>((thisMarker < s1.Length) && (thisChunk.Length==0 ||InChunk(thisCh, thisChunk[0])))</code>
<code> </code><code>thisChunk.Append(thisCh);</code>
<code> </code><code>thisMarker++;</code>
<code> </code><code>if</code> <code>(thisMarker < s1.Length)</code>
<code> </code><code>{</code>
<code> </code><code>thisCh = s1[thisMarker];</code>
<code> </code><code>}</code>
<code> </code><code>while</code> <code>((thatMarker < s2.Length) && (thatChunk.Length==0 ||InChunk(thatCh, thatChunk[0])))</code>
<code> </code><code>thatChunk.Append(thatCh);</code>
<code> </code><code>thatMarker++;</code>
<code> </code><code>if</code> <code>(thatMarker < s2.Length)</code>
<code> </code><code>thatCh = s2[thatMarker];</code>
<code> </code><code>int</code> <code>result = 0;</code>
<code> </code><code>// If both chunks contain numeric characters, sort them numerically</code>
<code> </code><code>if</code> <code>(</code><code>char</code><code>.IsDigit(thisChunk[0]) && </code><code>char</code><code>.IsDigit(thatChunk[0]))</code>
<code> </code><code>thisNumericChunk = Convert.ToInt32(thisChunk.ToString());</code>
<code> </code><code>thatNumericChunk = Convert.ToInt32(thatChunk.ToString());</code>
<code> </code><code>if</code> <code>(thisNumericChunk < thatNumericChunk)</code>
<code> </code><code>result = -1;</code>
<code> </code><code>if</code> <code>(thisNumericChunk > thatNumericChunk)</code>
<code> </code><code>result = 1;</code>
<code> </code><code>else</code>
<code> </code><code>result = thisChunk.ToString().CompareTo(thatChunk.ToString());</code>
<code> </code><code>if</code> <code>(result != 0)</code>
<code> </code><code>return</code> <code>result;</code>
<code> </code><code>return</code> <code>0;</code>
<code> </code><code>}</code>
<code>}</code>
本文轉自 h2appy 51CTO部落格,原文連結:http://blog.51cto.com/h2appy/1375457,如需轉載請自行聯系原作者